关键词搜索

源码搜索 ×
×

C# 如何识别一个字符串是否Json格式

发布2015-01-08浏览12819次

详情内容

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

原文地址: http://www.cnblogs.com/cyq1162/p/3841766.html

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载