首页 > 学院 > 开发设计 > 正文

浅谈C#手动解析Json格式内容

2019-11-17 02:47:19
字体:
来源:转载
供稿:网友

浅谈C#手动解析Json格式内容

这个应该算处女贴吧 - -

经过一位博友的点拨以下代码不包含转义的验证 还需各位自己添加在此不作修改 至于完善后的生成文件参见下一篇《C#深入解析Json格式内容》

之前百度了许久基本没有一个满意的json结构的解析类库 想了想还是自己做一个吧

现在我来说下大概的思路 首先我创建了一个JsonTokener的类 用于处理json字符串的一些操作里面有个枚举

 1     public enum JsonCharType 2     { 3         BeginObject = 123, //{ 4         EndObject = 125, //} 5         BeginArray = 91, //[ 6         EndArray = 93, //] 7         DoubleQuote = 34, //" 8         SingleQuote = 39, //' 9         Comma = 44,//,10         Split = 58, //:11         Slash = 92, ///12         BackSlash = 47, ///13         Right = 13, ///r14         Line = 10, ///n15         None = -1 //结尾或异常16     }

这些枚举数值代表了循环到的char状态 后面都有注释说明每个值代表的字符

  1  public sealed class JsonTokener  2     {  3         PRivate string jsonSource = string.Empty;  4         private int currentIndex = -1;  5   6         public int CurrentIndex  7         {  8             get { return currentIndex; }  9             set { currentIndex = value; } 10         } 11         private int countIndex = 0; 12  13         internal int lastIndex = 0; 14  15         public JsonTokener(string jsonSource) 16         { 17             this.jsonSource = jsonSource; 18             currentIndex = -1; 19             countIndex = jsonSource != null ? jsonSource.Length : 0; 20         } 21  22         /// <summary> 23         /// 向前推进一个字符 24         /// </summary> 25         /// <returns></returns> 26         public JsonCharType next() 27         { 28             currentIndex++; 29             return getCurrentIndex(); 30         } 31  32         public JsonCharType next(params JsonCharType[] types) 33         { 34             JsonCharType currentType = next(); 35             while ((int)currentType != -1) 36             { 37                 if (checkType(currentType, types)) 38                 { 39                     return currentType; 40                 } 41                 else 42                 { 43                     currentType = next(); 44                 } 45             } 46             return JsonCharType.None; 47         } 48  49         private bool checkType(JsonCharType currentType, JsonCharType[] types) 50         { 51             foreach (JsonCharType item in types) 52             { 53                 if (currentType == item) 54                     return true; 55             } 56             return false; 57         } 58  59         /// <summary> 60         /// 向后推后一个字符 61         /// </summary> 62         /// <returns></returns> 63         public JsonCharType back() 64         { 65             currentIndex--; 66             return getCurrentIndex(); 67         } 68  69         /// <summary> 70         /// 获得当前位置字符 71         /// </summary> 72         /// <returns></returns> 73         public JsonCharType current() 74         { 75             return getCurrentIndex(); 76         } 77  78         /// <summary> 79         /// 获得当前位置的字符 80         /// </summary> 81         /// <returns></returns> 82         private JsonCharType getCurrentIndex() 83         { 84             if (currentIndex >= 0 && currentIndex < countIndex) 85             { 86                 char c = jsonSource[currentIndex]; 87                 return (JsonCharType)Enum.ToObject(typeof(JsonCharType), c); 88             } 89             else 90             { 91                 currentIndex = countIndex; 92             } 93             //else 验证当前索引是否小于0 94             return JsonCharType.None; 95         } 96  97         /// <summary> 98         /// 查找该位置到下一个type间隔的文本 99         /// </summary>100         /// <param name="type"></param>101         /// <returns></returns>102         public string nextToType(JsonCharType type)103         {104             StringBuilder builder = new StringBuilder();105             JsonCharType currentType = next();106             while ((int)currentType != -1)107             {108                 if (currentType == type)109                 {110                     return builder.ToString();111                 }112                 else113                 {114                     builder.Append((char)currentType);115                     currentType = next();116                 }117             }118             throw new Exception("已到字符串末尾 没有找到相关匹配");119         }120     }

其中的操作无疑就代表了位移字符等一些操作 返回基本都是以JsonCharType为准

然后我又写了个类叫JsonSerialization 用于解析json结构

在此我就贴核心代码了 剩下的大家自己研究 要是都给出来就没意思了~

在这里我只提供思路

在JsonSerialization里有个FindObject的方法 还有个Deserializa用于解析json结构方法内有两个参数一个是JsonObject是我自己定义的 还有一个是 JsonTokener就是上面的类

public JsonObject Deserializa(){    JsonTokener tokener = new JsonTokener(jsonSource);    JsonObject parentNode = new JsonObject();    //解析object    FindObject(parentNode, tokener);    return parentNode;}

这个FindObject 基本实现思路

JsonCharType type = tokener.next(JsonCharType.BeginArray,JsonCharType.BeginObject,JsonCharType.EndArray,JsonCharType.EndObject,JsonCharType.SingleQuote,JsonCharType.DoubleQuote,JsonCharType.Split,JsonCharType.Comma);

首先寻找这些字符

一般一个完整的json结构传入都会以 { [ 开头 以] }结束 为了做到完美适配各种json结构 我加入了单引号识别和双引号识别

现在假设一个json结构 jsonp({"str_key":"value", "bool_test":true,"int_test":123,"double_test":12.7,"null_test":null,"array_test":["array1","array2",{"array_obj" : "array_obj"},["inner_array",1,12.2,true,null]]}) 当然上述的json结构是以jsonp跨域返回的串做的例子 我只是想证明 我做的这个解析会忽略掉jsonp头也就是说从第一个{开始解析或者第一个[开始解析

好了扯远了 既然找到了第一个列表包含的字符 那么就要进行进一步搜寻 也就是说还需要递归调用FindObject

所以第一个if也就有了

if (type == JsonCharType.BeginObject){    if (parentNode.IsArray)    {        JsonObject innerObj = new JsonObject();        //innerObj._parent = parentNode;        innerObj._isObject = true;        innerObj._sourceObj = new Dictionary<string, JsonObject>();        FindObject(innerObj, tokener);        parentNode.add(innerObj);        //继续寻找        FindObject(parentNode, tokener);    }    else    {        parentNode._isObject = true;        parentNode._sourceObj = new Dictionary<string, JsonObject>();        FindObject(parentNode, tokener);    }}

为什么要有个parentNode.IsArray的判断呢 是为了防止从上次递归过来的JsonObject为Array类型 然而递归到这里发现是Object的开头

所以只需要新构建个JsonObject然后在寻找更下层的层级嵌套 然后添加进去 在继续寻找直到找完位置

那个else的意思是代表了如果这个是初始化的操作也就是说一个没有经过任何设置的JsonObject进行一个初始化并开始递归寻找

else if (type == JsonCharType.BeginArray){    tokener.lastIndex = tokener.CurrentIndex;    if (parentNode.IsObject)    {        JsonObject innerObj = new JsonObject();        //innerObj._parent = parentNode;        FindObject(innerObj, tokener);        parentNode.add(innerObj);        //继续寻找        FindObject(parentNode, tokener);    }    else    {        if (parentNode.IsArray)        {            JsonObject innerObj = new JsonObject();            //innerObj._parent = parentNode;            innerObj._isArray = true;            innerObj._sourceObj = new List<JsonObject>();            FindObject(innerObj, tokener);            parentNode.add(innerObj);            //继续寻找            FindObject(parentNode, tokener);        }        else        {            parentNode._isArray = true;            parentNode._sourceObj = new List<JsonObject>();            FindObject(parentNode, tokener);        }    }}

这段代码是接上面的我一段一段的解释

这段代码意思是当发现起始json array结构时 判断 上一个递归过来的节点是不是json object类型 如果是就构建一个新的JsonObject并添加

如果不是的话判断上一个节点过来的是不是json array结构 如果是json array结构则又需要构建一个JsonObject 并添加

否则进行初始化设定并继续寻找

else if (type == JsonCharType.DoubleQuote || type == JsonCharType.SingleQuote){    if (parentNode.IsObject)    {        //找寻key        string _key = tokener.nextToType(type);        JsonObject innerObj = new JsonObject();        //innerObj._parent = parentNode;        innerObj._key = _key;        FindObject(innerObj, tokener);        parentNode.add(innerObj);        //继续寻找        FindObject(parentNode, tokener);    }    else if (parentNode.IsArray)    {        //找到value并添加value        string _value = tokener.nextToType(type);        JsonObject obj = new JsonObject();        //obj._parent = parentN
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表