JsonSplit.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. namespace Ant.Service.Common
  6. {
  7. /// <summary>
  8. /// 判断字符串是否为JSON
  9. /// </summary>
  10. public class JsonSplit
  11. {
  12. private static bool IsJsonStart(ref string json)
  13. {
  14. if (!string.IsNullOrEmpty(json))
  15. {
  16. json = json.Trim('\r', '\n', ' ');
  17. if (json.Length > 1)
  18. {
  19. char s = json[0];
  20. char e = json[json.Length - 1];
  21. return (s == '{' && e == '}') || (s == '[' && e == ']');
  22. }
  23. }
  24. return false;
  25. }
  26. public static bool IsJson(string json)
  27. {
  28. int errIndex;
  29. return IsJson(json, out errIndex);
  30. }
  31. public static bool IsJson(string json, out int errIndex)
  32. {
  33. errIndex = 0;
  34. if (IsJsonStart(ref json))
  35. {
  36. CharState cs = new CharState();
  37. char c;
  38. for (int i = 0; i < json.Length; i++)
  39. {
  40. c = json[i];
  41. if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
  42. {
  43. string item = json.Substring(i);
  44. int err;
  45. int length = GetValueLength(item, true, out err);
  46. cs.childrenStart = false;
  47. if (err > 0)
  48. {
  49. errIndex = i + err;
  50. return false;
  51. }
  52. i = i + length - 1;
  53. }
  54. if (cs.isError)
  55. {
  56. errIndex = i;
  57. return false;
  58. }
  59. }
  60. return !cs.arrayStart && !cs.jsonStart;
  61. }
  62. return false;
  63. }
  64. /// <summary>
  65. /// 获取值的长度(当Json值嵌套以"{"或"["开头时)
  66. /// </summary>
  67. private static int GetValueLength(string json, bool breakOnErr, out int errIndex)
  68. {
  69. errIndex = 0;
  70. int len = 0;
  71. if (!string.IsNullOrEmpty(json))
  72. {
  73. CharState cs = new CharState();
  74. char c;
  75. for (int i = 0; i < json.Length; i++)
  76. {
  77. c = json[i];
  78. if (!SetCharState(c, ref cs))//设置关键符号状态。
  79. {
  80. if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。
  81. {
  82. break;
  83. }
  84. }
  85. else if (cs.childrenStart)//正常字符,值状态下。
  86. {
  87. int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。
  88. cs.childrenStart = false;
  89. cs.valueStart = 0;
  90. //cs.state = 0;
  91. i = i + length - 1;
  92. }
  93. if (breakOnErr && cs.isError)
  94. {
  95. errIndex = i;
  96. return i;
  97. }
  98. if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
  99. {
  100. len = i + 1;//长度比索引+1
  101. break;
  102. }
  103. }
  104. }
  105. return len;
  106. }
  107. /// <summary>
  108. /// 字符状态
  109. /// </summary>
  110. private class CharState
  111. {
  112. internal bool jsonStart = false;//以 "{"开始了...
  113. internal bool setDicValue = false;// 可以设置字典值了。
  114. internal bool escapeChar = false;//以"\"转义符号开始了
  115. /// <summary>
  116. /// 数组开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。
  117. /// </summary>
  118. internal bool arrayStart = false;//以"[" 符号开始了
  119. internal bool childrenStart = false;//子级嵌套开始了。
  120. /// <summary>
  121. /// 【0 初始状态,或 遇到“,”逗号】;【1 遇到“:”冒号】
  122. /// </summary>
  123. internal int state = 0;
  124. /// <summary>
  125. /// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
  126. /// </summary>
  127. internal int keyStart = 0;
  128. /// <summary>
  129. /// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】
  130. /// </summary>
  131. internal int valueStart = 0;
  132. internal bool isError = false;//是否语法错误。
  133. internal void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理)
  134. {
  135. if (keyStart > 1 || valueStart > 1)
  136. {
  137. return;
  138. }
  139. //示例 ["aa",{"bbbb":123,"fff","ddd"}]
  140. switch (c)
  141. {
  142. case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
  143. isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。
  144. break;
  145. case '}':
  146. isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 或者 提前结束{"aa"}。正常的有{}
  147. break;
  148. case '[':
  149. isError = arrayStart && state == 0;//重复开始错误
  150. break;
  151. case ']':
  152. isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束
  153. break;
  154. case '"':
  155. case '\'':
  156. isError = !(jsonStart || arrayStart); //json 或数组开始。
  157. if (!isError)
  158. {
  159. //重复开始 [""",{"" "}]
  160. isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1);
  161. }
  162. if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
  163. {
  164. isError = true;
  165. }
  166. break;
  167. case ':':
  168. isError = !jsonStart || state == 1;//重复出现。
  169. break;
  170. case ',':
  171. isError = !(jsonStart || arrayStart); //json 或数组开始。
  172. if (!isError)
  173. {
  174. if (jsonStart)
  175. {
  176. isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。
  177. }
  178. else if (arrayStart)//["aa,] [,] [{},{}]
  179. {
  180. isError = keyStart == 0 && !setDicValue;
  181. }
  182. }
  183. break;
  184. case ' ':
  185. case '\r':
  186. case '\n'://[ "a",\r\n{} ]
  187. case '\0':
  188. case '\t':
  189. break;
  190. default: //值开头。。
  191. isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);//
  192. break;
  193. }
  194. //if (isError)
  195. //{
  196. //}
  197. }
  198. }
  199. /// <summary>
  200. /// 设置字符状态(返回true则为关键词,返回false则当为普通字符处理)
  201. /// </summary>
  202. private static bool SetCharState(char c, ref CharState cs)
  203. {
  204. cs.CheckIsError(c);
  205. switch (c)
  206. {
  207. case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]
  208. #region 大括号
  209. if (cs.keyStart <= 0 && cs.valueStart <= 0)
  210. {
  211. cs.keyStart = 0;
  212. cs.valueStart = 0;
  213. if (cs.jsonStart && cs.state == 1)
  214. {
  215. cs.childrenStart = true;
  216. }
  217. else
  218. {
  219. cs.state = 0;
  220. }
  221. cs.jsonStart = true;//开始。
  222. return true;
  223. }
  224. #endregion
  225. break;
  226. case '}':
  227. #region 大括号结束
  228. if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart)
  229. {
  230. cs.jsonStart = false;//正常结束。
  231. cs.state = 0;
  232. cs.keyStart = 0;
  233. cs.valueStart = 0;
  234. cs.setDicValue = true;
  235. return true;
  236. }
  237. // cs.isError = !cs.jsonStart && cs.state == 0;
  238. #endregion
  239. break;
  240. case '[':
  241. #region 中括号开始
  242. if (!cs.jsonStart)
  243. {
  244. cs.arrayStart = true;
  245. return true;
  246. }
  247. else if (cs.jsonStart && cs.state == 1)
  248. {
  249. cs.childrenStart = true;
  250. return true;
  251. }
  252. #endregion
  253. break;
  254. case ']':
  255. #region 中括号结束
  256. if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
  257. {
  258. cs.keyStart = 0;
  259. cs.valueStart = 0;
  260. cs.arrayStart = false;
  261. return true;
  262. }
  263. #endregion
  264. break;
  265. case '"':
  266. case '\'':
  267. #region 引号
  268. if (cs.jsonStart || cs.arrayStart)
  269. {
  270. if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
  271. {
  272. if (cs.keyStart <= 0)
  273. {
  274. cs.keyStart = (c == '"' ? 3 : 2);
  275. return true;
  276. }
  277. else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"'))
  278. {
  279. if (!cs.escapeChar)
  280. {
  281. cs.keyStart = -1;
  282. return true;
  283. }
  284. else
  285. {
  286. cs.escapeChar = false;
  287. }
  288. }
  289. }
  290. else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
  291. {
  292. if (cs.valueStart <= 0)
  293. {
  294. cs.valueStart = (c == '"' ? 3 : 2);
  295. return true;
  296. }
  297. else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"'))
  298. {
  299. if (!cs.escapeChar)
  300. {
  301. cs.valueStart = -1;
  302. return true;
  303. }
  304. else
  305. {
  306. cs.escapeChar = false;
  307. }
  308. }
  309. }
  310. }
  311. #endregion
  312. break;
  313. case ':':
  314. #region 冒号
  315. if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0)
  316. {
  317. if (cs.keyStart == 1)
  318. {
  319. cs.keyStart = -1;
  320. }
  321. cs.state = 1;
  322. return true;
  323. }
  324. // cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);
  325. #endregion
  326. break;
  327. case ',':
  328. #region 逗号 //["aa",{aa:12,}]
  329. if (cs.jsonStart)
  330. {
  331. if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1)
  332. {
  333. cs.state = 0;
  334. cs.keyStart = 0;
  335. cs.valueStart = 0;
  336. //if (cs.valueStart == 1)
  337. //{
  338. // cs.valueStart = 0;
  339. //}
  340. cs.setDicValue = true;
  341. return true;
  342. }
  343. }
  344. else if (cs.arrayStart && cs.keyStart <= 2)
  345. {
  346. cs.keyStart = 0;
  347. //if (cs.keyStart == 1)
  348. //{
  349. // cs.keyStart = -1;
  350. //}
  351. return true;
  352. }
  353. #endregion
  354. break;
  355. case ' ':
  356. case '\r':
  357. case '\n'://[ "a",\r\n{} ]
  358. case '\0':
  359. case '\t':
  360. if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
  361. {
  362. return true;//跳过空格。
  363. }
  364. break;
  365. default: //值开头。。
  366. if (c == '\\') //转义符号
  367. {
  368. if (cs.escapeChar)
  369. {
  370. cs.escapeChar = false;
  371. }
  372. else
  373. {
  374. cs.escapeChar = true;
  375. return true;
  376. }
  377. }
  378. else
  379. {
  380. cs.escapeChar = false;
  381. }
  382. if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。
  383. {
  384. if (cs.keyStart <= 0 && cs.state == 0)
  385. {
  386. cs.keyStart = 1;//无引号的
  387. }
  388. else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
  389. {
  390. cs.valueStart = 1;//无引号的
  391. }
  392. }
  393. break;
  394. }
  395. return false;
  396. }
  397. }
  398. }