JsonParsor.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. using XGame.Framework.Utils;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Text;
  6. namespace XGame.Framework.Json
  7. {
  8. public class JsonParsor
  9. {
  10. private const int TokenNone = 0;
  11. /// <summary>
  12. /// 花括号 {
  13. /// </summary>
  14. private const int TokenCurlyOpen = 1;
  15. /// <summary>
  16. /// 花括号 }
  17. /// </summary>
  18. private const int TokenCurlyClose = 2;
  19. /// <summary>
  20. ///
  21. /// </summary>
  22. private const int TokenSquaredOpen = 3;
  23. /// <summary>
  24. /// 方括号 ]
  25. /// </summary>
  26. private const int TokenSquaredClose = 4;
  27. /// <summary>
  28. /// 冒号 :
  29. /// </summary>
  30. private const int TokenColon = 5;
  31. /// <summary>
  32. /// 逗号 ,
  33. /// </summary>
  34. private const int TokenComma = 6;
  35. /// <summary>
  36. /// 字符串 string
  37. /// </summary>
  38. private const int TokenString = 7;
  39. /// <summary>
  40. /// 数字 number
  41. /// </summary>
  42. private const int TokenNumber = 8;
  43. /// <summary>
  44. /// bool值 true
  45. /// </summary>
  46. private const int TokenTrue = 9;
  47. /// <summary>
  48. /// bool值 false
  49. /// </summary>
  50. private const int TokenFalse = 10;
  51. /// <summary>
  52. /// 空 null
  53. /// </summary>
  54. private const int TokenNull = 11;
  55. public bool TryDeserializeObject(string json, out object obj)
  56. {
  57. bool success = true;
  58. obj = null;
  59. if (json != null)
  60. {
  61. char[] charArray = json.ToCharArray();
  62. int index = 0;
  63. obj = ParseValue(charArray, ref index, ref success);
  64. //PrintDict(obj);
  65. }
  66. return success;
  67. }
  68. #region 对json进行解析
  69. // 开始处理json字符串的每个字符
  70. private object ParseValue(char[] json, ref int index, ref bool success)
  71. {
  72. switch (LookAhead(json, index))
  73. {
  74. case TokenString:
  75. return ParseString(json, ref index, ref success);
  76. case TokenNumber:
  77. return ParseNumber(json, ref index, ref success);
  78. case TokenCurlyOpen:
  79. return ParseObject(json, ref index, ref success);
  80. case TokenSquaredOpen:
  81. return ParseArray(json, ref index, ref success);
  82. case TokenTrue:
  83. NextToken(json, ref index);
  84. return true;
  85. case TokenFalse:
  86. NextToken(json, ref index);
  87. return false;
  88. case TokenNull:
  89. NextToken(json, ref index);
  90. return null;
  91. case TokenNone:
  92. break;
  93. }
  94. success = false;
  95. return null;
  96. }
  97. // 特殊字符跳过
  98. private void DealWithWhitespace(char[] json, ref int index)
  99. {
  100. for (int length = json.Length; index < length; index++)
  101. {
  102. if (" \t\n\r\b\f".IndexOf(json[index]) == -1)
  103. break;
  104. }
  105. }
  106. // 前瞻
  107. private int LookAhead(char[] json, int index)
  108. {
  109. int saveIndex = index;
  110. return NextToken(json, ref saveIndex);
  111. }
  112. // json字符判断
  113. private int NextToken(char[] json, ref int index)
  114. {
  115. DealWithWhitespace(json, ref index);
  116. if (index == json.Length) return TokenNone;
  117. char c = json[index];
  118. index++;
  119. // 字符判断
  120. switch (c)
  121. {
  122. case '{':
  123. return TokenCurlyOpen;
  124. case '}':
  125. return TokenCurlyClose;
  126. case '[':
  127. return TokenSquaredOpen;
  128. case ']':
  129. return TokenSquaredClose;
  130. case ':':
  131. return TokenColon;
  132. case ',':
  133. return TokenComma;
  134. case '"':
  135. return TokenString;
  136. case '0':
  137. case '1':
  138. case '2':
  139. case '3':
  140. case '4':
  141. case '5':
  142. case '6':
  143. case '7':
  144. case '8':
  145. case '9':
  146. case '-':
  147. return TokenNumber;
  148. }
  149. // 剩余字符长度
  150. index--;
  151. int remainingLength = json.Length - index;
  152. // 字符串false
  153. if (remainingLength >= 5)
  154. {
  155. if (json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e')
  156. {
  157. index += 5;
  158. return TokenFalse;
  159. }
  160. }
  161. // 字符串true
  162. if (remainingLength >= 4)
  163. {
  164. if (json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e')
  165. {
  166. index += 4;
  167. return TokenTrue;
  168. }
  169. }
  170. // 字符串null
  171. if (remainingLength >= 4)
  172. {
  173. if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l')
  174. {
  175. index += 4;
  176. return TokenNull;
  177. }
  178. }
  179. return TokenNone;
  180. }
  181. #region ParseString
  182. private string ParseString(char[] json, ref int index, ref bool success)
  183. {
  184. StringBuilder builder = StringBuilderUtils.Acquire();
  185. DealWithWhitespace(json, ref index);
  186. char c = json[index++];
  187. bool complete = false;
  188. while (!complete)
  189. {
  190. if (index == json.Length) break;
  191. c = json[index++];
  192. switch (c)
  193. {
  194. case '"':
  195. complete = true;
  196. break;
  197. case '\\':
  198. if (index == json.Length) break;
  199. c = json[index++];
  200. switch (c)
  201. {
  202. case '"':
  203. builder.Append('"');
  204. break;
  205. case '\\':
  206. builder.Append('\\');
  207. break;
  208. case '\'':
  209. builder.Append('\'');
  210. break;
  211. case '/':
  212. builder.Append('/');
  213. break;
  214. case 'b':
  215. builder.Append('\b');
  216. break;
  217. case 'f':
  218. builder.Append('\f');
  219. break;
  220. case 'n':
  221. builder.Append('\n');
  222. break;
  223. case 'r':
  224. builder.Append('\r');
  225. break;
  226. case 't':
  227. builder.Append('\t');
  228. break;
  229. case 'u':
  230. int remainingLength = json.Length - index;
  231. if (remainingLength >= 4)
  232. {
  233. uint codePoint;
  234. // 将32位十六进制解析为无符号整型
  235. if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint)))
  236. throw new SystemException("can not parse the 32 bit hex into an integer codepoint");
  237. // 将整型转换为unicode字符并添加到字符串中
  238. if (0xD800 <= codePoint && codePoint <= 0xDBFF) // if high surrogate
  239. {
  240. index += 4; // skip 4 chars
  241. remainingLength = json.Length - index;
  242. if (remainingLength >= 6)
  243. {
  244. uint lowCodePoint;
  245. if (new string(json, index, 2) == "\\u" && UInt32.TryParse(new string(json, index + 2, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out lowCodePoint))
  246. {
  247. if (0xDC00 <= lowCodePoint && lowCodePoint <= 0xDFFF) // if low surrogate
  248. {
  249. builder.Append((char)codePoint);
  250. builder.Append((char)lowCodePoint);
  251. index += 6; // skip 6 chars
  252. continue;
  253. }
  254. }
  255. }
  256. success = false; // invalid surrogate pair
  257. StringBuilderUtils.Release(builder);
  258. return "";
  259. }
  260. builder.Append(ConvertFromUtf32((int)codePoint));
  261. // skip 4 chars
  262. index += 4;
  263. }
  264. break;
  265. }
  266. break;
  267. default:
  268. builder.Append(c);
  269. break;
  270. }
  271. }
  272. if (!complete)
  273. {
  274. success = false;
  275. StringBuilderUtils.Release(builder);
  276. return null;
  277. }
  278. return StringBuilderUtils.GetStringAndRelease(builder);
  279. }
  280. // Unicode编码转换为UTF-32
  281. private string ConvertFromUtf32(int utf32)
  282. {
  283. if (utf32 < 0 || utf32 > 0x10FFFF)
  284. throw new ArgumentOutOfRangeException(nameof(utf32), "The argument must be from 0 to 0x10FFFF.");
  285. if (0xD800 <= utf32 && utf32 <= 0xDFFF)
  286. throw new ArgumentOutOfRangeException(nameof(utf32), "The argument must not be in surrogate pair range.");
  287. if (utf32 < 0x10000)
  288. return new string((char)utf32, 1);
  289. utf32 -= 0x10000;
  290. return new string(new char[] { (char)((utf32 >> 10) + 0xD800), (char)(utf32 % 0x0400 + 0xDC00) });
  291. }
  292. #endregion
  293. #region ParseNumber
  294. private object ParseNumber(char[] json, ref int index, ref bool success)
  295. {
  296. DealWithWhitespace(json, ref index);
  297. // 获取数字的字符串
  298. int lastIndex = GetLastIndexOfNumber(json, index);
  299. int numLength = (lastIndex - index) + 1;
  300. string numStr = new string(json, index, numLength);
  301. object changeNum;
  302. if (numStr.IndexOf(".", StringComparison.OrdinalIgnoreCase) != -1 || numStr.IndexOf("e", StringComparison.OrdinalIgnoreCase) != -1)
  303. {
  304. success = double.TryParse(new string(json, index, numLength), NumberStyles.Any, CultureInfo.InvariantCulture, out var number);
  305. changeNum = number;
  306. }
  307. else
  308. {
  309. success = long.TryParse(new string(json, index, numLength), NumberStyles.Any, CultureInfo.InvariantCulture, out var number);
  310. changeNum = number;
  311. }
  312. index = lastIndex + 1;
  313. return changeNum;
  314. }
  315. private int GetLastIndexOfNumber(char[] json, int index)
  316. {
  317. int lastIndex = index;
  318. for (int length = json.Length; lastIndex < length; lastIndex++)
  319. {
  320. if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) break;
  321. }
  322. return lastIndex - 1;
  323. }
  324. #endregion
  325. #region ParseObject
  326. private Dictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
  327. {
  328. Dictionary<string, object> map = new Dictionary<string, object>();
  329. DealWithWhitespace(json, ref index);
  330. // 跳过 {
  331. index++;
  332. int token = index;
  333. bool complete = false;
  334. while (!complete)
  335. {
  336. token = LookAhead(json, index);
  337. switch (token)
  338. {
  339. case TokenNone:
  340. success = false;
  341. return null;
  342. case TokenComma:
  343. NextToken(json, ref index);
  344. break;
  345. case TokenCurlyClose:
  346. NextToken(json, ref index);
  347. return map;
  348. default:
  349. // key
  350. string key = ParseString(json, ref index, ref success);
  351. if (!success) return null;
  352. // :
  353. token = NextToken(json, ref index);
  354. if (token != TokenColon)
  355. {
  356. success = false;
  357. return null;
  358. }
  359. // value
  360. object value = ParseValue(json, ref index, ref success);
  361. if (!success) return null;
  362. map.Add(key, value);
  363. break;
  364. }
  365. }
  366. return map;
  367. }
  368. #endregion
  369. #region ParseArray
  370. private List<object> ParseArray(char[] json, ref int index, ref bool success)
  371. {
  372. List<object> list = new List<object>();
  373. DealWithWhitespace(json, ref index);
  374. index++;
  375. int token = index;
  376. bool complete = false;
  377. while (!complete)
  378. {
  379. token = LookAhead(json, index);
  380. switch (token)
  381. {
  382. case TokenNone:
  383. success = false;
  384. return null;
  385. case TokenComma:
  386. NextToken(json, ref index);
  387. break;
  388. case TokenSquaredClose:
  389. NextToken(json, ref index);
  390. complete = true;
  391. break;
  392. default:
  393. // value
  394. object value = ParseValue(json, ref index, ref success);
  395. if (!success) return null;
  396. list.Add(value);
  397. break;
  398. }
  399. }
  400. return list;
  401. }
  402. #endregion
  403. #endregion
  404. }
  405. }