using System; using System.Collections.Generic; using System.Text; namespace CYQ.Data.Tool { /// <summary> /// 分开Json字符串为字典鸠合。 /// </summary> internal class JsonSplit { private static bool IsJsonStart(ref string json) { if (!string.IsNullOrEmpty(json)) { json = json.Trim('\r', '\n', ' '); if (json.Length > 1) { char s = json[0]; char e = json[json.Length - 1]; return (s == '{' && e == '}') || (s == '[' && e == ']'); } } return false; } internal static bool IsJson(string json) { int errIndex; return IsJson(json, out errIndex); } internal static bool IsJson(string json, out int errIndex) { errIndex = 0; if (IsJsonStart(ref json)) { CharState cs = new CharState(); char c; for (int i = 0; i < json.Length; i++) { c = json[i]; if (SetCharState(c, ref cs) && cs.childrenStart)//设置症结标记状况。 { string item = json.Substring(i); int err; int length = GetValueLength(item, true, out err); cs.childrenStart = false; if (err > 0) { errIndex = i + err; return false; } i = i + length - 1; } if (cs.isError) { errIndex = i; return false; } } return !cs.arrayStart && !cs.jsonStart; } return false; } /// <summary> /// 获取值的长度(当Json值嵌套以"{"或"["开首时) /// </summary> private static int GetValueLength(string json, bool breakOnErr, out int errIndex) { errIndex = 0; int len = 0; if (!string.IsNullOrEmpty(json)) { CharState cs = new CharState(); char c; for (int i = 0; i < json.Length; i++) { c = json[i]; if (!SetCharState(c, ref cs))//设置症结标记状况。 { if (!cs.jsonStart && !cs.arrayStart)//json完毕,又不是数组,则退出。 { break; } } else if (cs.childrenStart)//一般字符,值状况下。 { int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。 cs.childrenStart = false; cs.valueStart = 0; //cs.state = 0; i = i + length - 1; } if (breakOnErr && cs.isError) { errIndex = i; return i; } if (!cs.jsonStart && !cs.arrayStart)//纪录当前完毕位置。 { len = i + 1;//长度比索引+1 break; } } } return len; } /// <summary> /// 字符状况 /// </summary> private class CharState { internal bool jsonStart = false;//以 "{"最先了... internal bool setDicValue = false;// 能够设置字典值了。 internal bool escapeChar = false;//以"\"转义标记最先了 /// <summary> /// 数组最先【仅第一开首才算】,值嵌套的以【childrenStart】来标识。 /// </summary> internal bool arrayStart = false;//以"[" 标记最先了 internal bool childrenStart = false;//子级嵌套最先了。 /// <summary> /// 【0 初始状况,或 碰到“,”逗号】;【1 碰到“:”冒号】 /// </summary> internal int state = 0; /// <summary> /// 【-1 取值完毕】【0 未最先】【1 无引号最先】【2 单引号最先】【3 双引号最先】 /// </summary> internal int keyStart = 0; /// <summary> /// 【-1 取值完毕】【0 未最先】【1 无引号最先】【2 单引号最先】【3 双引号最先】 /// </summary> internal int valueStart = 0; internal bool isError = false;//是不是语法毛病。 internal void CheckIsError(char c)//只当做一级处置惩罚(由于GetLength会递归到每个子项处置惩罚) { if (keyStart > 1 || valueStart > 1) { return; } //示例 ["aa",{"bbbb":123,"fff","ddd"}] switch (c) { case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}] isError = jsonStart && state == 0;//反复最先毛病 同时不是值处置惩罚。 break; case '}': isError = !jsonStart || (keyStart != 0 && state == 0);//反复完毕毛病 或许 提前完毕{"aa"}。一般的有{} break; case '[': isError = arrayStart && state == 0;//反复最先毛病 break; case ']': isError = !arrayStart || jsonStart;//反复最先毛病 或许 Json 未完毕 break; case '"': case '\'': isError = !(jsonStart || arrayStart); //json 或数组最先。 if (!isError) { //反复最先 [""",{"" "}] isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1); } if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}] { isError = true; } break; case ':': isError = !jsonStart || state == 1;//反复涌现。 break; case ',': isError = !(jsonStart || arrayStart); //json 或数组最先。 if (!isError) { if (jsonStart) { isError = state == 0 || (state == 1 && valueStart > 1);//反复涌现。 } else if (arrayStart)//["aa,] [,] [{},{}] { isError = keyStart == 0 && !setDicValue; } } break; case ' ': case '\r': case '\n'://[ "a",\r\n{} ] case '\0': case '\t': break; default: //值开首。。 isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);// break; } //if (isError) //{ //} } } /// <summary> /// 设置字符状况(返回true则为症结词,返回false则当为一般字符处置惩罚) /// </summary> private static bool SetCharState(char c, ref CharState cs) { cs.CheckIsError(c); switch (c) { case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}] #region 大括号 if (cs.keyStart <= 0 && cs.valueStart <= 0) { cs.keyStart = 0; cs.valueStart = 0; if (cs.jsonStart && cs.state == 1) { cs.childrenStart = true; } else { cs.state = 0; } cs.jsonStart = true;//最先。 return true; } #endregion break; case '}': #region 大括号完毕 if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart) { cs.jsonStart = false;//一般完毕。 cs.state = 0; cs.keyStart = 0; cs.valueStart = 0; cs.setDicValue = true; return true; } // cs.isError = !cs.jsonStart && cs.state == 0; #endregion break; case '[': #region 中括号最先 if (!cs.jsonStart) { cs.arrayStart = true; return true; } else if (cs.jsonStart && cs.state == 1) { cs.childrenStart = true; return true; } #endregion break; case ']': #region 中括号完毕 if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//如许完毕。 { cs.keyStart = 0; cs.valueStart = 0; cs.arrayStart = false; return true; } #endregion break; case '"': case '\'': #region 引号 if (cs.jsonStart || cs.arrayStart) { if (cs.state == 0)//key阶段,有多是数组["aa",{}] { if (cs.keyStart <= 0) { cs.keyStart = (c == '"' ? 3 : 2); return true; } else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"')) { if (!cs.escapeChar) { cs.keyStart = -1; return true; } else { cs.escapeChar = false; } } } else if (cs.state == 1 && cs.jsonStart)//值阶段必需是Json最先了。 { if (cs.valueStart <= 0) { cs.valueStart = (c == '"' ? 3 : 2); return true; } else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"')) { if (!cs.escapeChar) { cs.valueStart = -1; return true; } else { cs.escapeChar = false; } } } } #endregion break; case ':': #region 冒号 if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0) { if (cs.keyStart == 1) { cs.keyStart = -1; } cs.state = 1; return true; } // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1); #endregion break; case ',': #region 逗号 //["aa",{aa:12,}] if (cs.jsonStart) { if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1) { cs.state = 0; cs.keyStart = 0; cs.valueStart = 0; //if (cs.valueStart == 1) //{ // cs.valueStart = 0; //} cs.setDicValue = true; return true; } } else if (cs.arrayStart && cs.keyStart <= 2) { cs.keyStart = 0; //if (cs.keyStart == 1) //{ // cs.keyStart = -1; //} return true; } #endregion break; case ' ': case '\r': case '\n'://[ "a",\r\n{} ] case '\0': case '\t': if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart && { return true;//跳过空格。 } break; default: //值开首。。 if (c == '\\') //转义标记 { if (cs.escapeChar) { cs.escapeChar = false; } else { cs.escapeChar = true; return true; } } else { cs.escapeChar = false; } if (cs.jsonStart || cs.arrayStart) // Json 或数组最先了。 { if (cs.keyStart <= 0 && cs.state == 0) { cs.keyStart = 1;//无引号的 } else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只要Json最先才有值。 { cs.valueStart = 1;//无引号的 } } break; } return false; } } }
以上就是C# 怎样辨认一个字符串是不是Json花样 的内容,更多相关内容请关注ki4网(www.ki4.cn)!