這個應該算處女貼吧 - -
經過一位博友的點撥以下代碼不包含轉義的驗證 還需各位自己添加在此不作修改 至于完善后的生成文件參見下一篇《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
新聞熱點
疑難解答