SimpleJSON.cs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  1. /* * * * *
  2. * A simple JSON Parser / builder
  3. * ------------------------------
  4. *
  5. * It mainly has been written as a simple JSON parser. It can build a JSON string
  6. * from the node-tree, or generate a node tree from any valid JSON string.
  7. *
  8. * If you want to use compression when saving to file / stream / B64 you have to include
  9. * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
  10. * define "USE_SharpZipLib" at the top of the file
  11. *
  12. * Written by Bunny83
  13. * 2012-06-09
  14. *
  15. * [2012-06-09 First Version]
  16. * - provides strongly typed node classes and lists / dictionaries
  17. * - provides easy access to class members / array items / data values
  18. * - the parser now properly identifies types. So generating JSON with this framework should work.
  19. * - only double quotes (") are used for quoting strings.
  20. * - provides "casting" properties to easily convert to / from those types:
  21. * int / float / double / bool
  22. * - provides a common interface for each node so no explicit casting is required.
  23. * - the parser tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined
  24. * - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might
  25. * be handy if you want to store things in a file and don't want it to be easily modifiable
  26. *
  27. *
  28. * [2012-12-17 Update]
  29. * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
  30. * Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
  31. * The class determines the required type by it's further use, creates the type and removes itself.
  32. * - Added binary serialization / deserialization.
  33. * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
  34. * The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
  35. * - The serializer uses different types when it comes to store the values. Since my data values
  36. * are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
  37. * It's not the most efficient way but for a moderate amount of data it should work on all platforms.
  38. *
  39. * [2017-03-08 Update]
  40. * - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large
  41. * string data fields are contained in the json data.
  42. * - Finally refactored the badly named JSONClass into JSONObject.
  43. * - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this
  44. * allows to propertly convert the node tree back to json without type information loss. The actual value
  45. * parsing now happens at parsing time and not when you actually access one of the casting properties.
  46. *
  47. * [2017-04-11 Update]
  48. * - Fixed parsing bug where empty string values have been ignored.
  49. * - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files
  50. * - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)"
  51. *
  52. * [2017-11-29 Update]
  53. * - Removed the IEnumerator implementations on JSONArray & JSONObject and replaced it with a common
  54. * struct Enumerator in JSONNode that should avoid garbage generation. The enumerator always works
  55. * on KeyValuePair<string, JSONNode>, even for JSONArray.
  56. * - Added two wrapper Enumerators that allows for easy key or value enumeration. A JSONNode now has
  57. * a "Keys" and a "Values" enumerable property. Those are also struct enumerators / enumerables
  58. * - A KeyValuePair<string, JSONNode> can now be implicitly converted into a JSONNode. This allows
  59. * a foreach loop over a JSONNode to directly access the values only. Since KeyValuePair as well as
  60. * all the Enumerators are structs, no garbage is allocated.
  61. * - To add Linq support another "LinqEnumerator" is available through the "Linq" property. This
  62. * enumerator does implement the generic IEnumerable interface so most Linq extensions can be used
  63. * on this enumerable object. This one does allocate memory as it's a wrapper class.
  64. * - The Escape method now escapes all control characters (# < 32) in strings as uncode characters
  65. * (\uXXXX) and if the static bool JSONNode.forceASCII is set to true it will also escape all
  66. * characters # > 127. This might be useful if you require an ASCII output. Though keep in mind
  67. * when your strings contain many non-ascii characters the strings become much longer (x6) and are
  68. * no longer human readable.
  69. * - The node types JSONObject and JSONArray now have an "Inline" boolean switch which will default to
  70. * false. It can be used to serialize this element inline even you serialize with an indented format
  71. * This is useful for arrays containing numbers so it doesn't place every number on a new line
  72. * - Extracted the binary serialization code into a seperate extension file. All classes are now declared
  73. * as "partial" so an extension file can even add a new virtual or abstract method / interface to
  74. * JSONNode and override it in the concrete type classes. It's of course a hacky approach which is
  75. * generally not recommended, but i wanted to keep everything tightly packed.
  76. * - Added a static CreateOrGet method to the JSONNull class. Since this class is immutable it could
  77. * be reused without major problems. If you have a lot null fields in your data it will help reduce
  78. * the memory / garbage overhead. I also added a static setting (reuseSameInstance) to JSONNull
  79. * (default is true) which will change the behaviour of "CreateOrGet". If you set this to false
  80. * CreateOrGet will not reuse the cached instance but instead create a new JSONNull instance each time.
  81. * I made the JSONNull constructor private so if you need to create an instance manually use
  82. * JSONNull.CreateOrGet()
  83. *
  84. *
  85. * The MIT License (MIT)
  86. *
  87. * Copyright (c) 2012-2017 Markus Göbel (Bunny83)
  88. *
  89. * Permission is hereby granted, free of charge, to any person obtaining a copy
  90. * of this software and associated documentation files (the "Software"), to deal
  91. * in the Software without restriction, including without limitation the rights
  92. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  93. * copies of the Software, and to permit persons to whom the Software is
  94. * furnished to do so, subject to the following conditions:
  95. *
  96. * The above copyright notice and this permission notice shall be included in all
  97. * copies or substantial portions of the Software.
  98. *
  99. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  100. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  101. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  102. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  103. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  104. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  105. * SOFTWARE.
  106. *
  107. * * * * */
  108. using System;
  109. using System.Collections;
  110. using System.Collections.Generic;
  111. using System.Linq;
  112. using System.Text;
  113. namespace SimpleJSON
  114. {
  115. public enum JSONNodeType
  116. {
  117. Array = 1,
  118. Object = 2,
  119. String = 3,
  120. Number = 4,
  121. NullValue = 5,
  122. Boolean = 6,
  123. None = 7,
  124. Custom = 0xFF,
  125. }
  126. public enum JSONTextMode
  127. {
  128. Compact,
  129. Indent
  130. }
  131. public abstract partial class JSONNode
  132. {
  133. #region Enumerators
  134. public struct Enumerator
  135. {
  136. private enum Type { None, Array, Object }
  137. private Type type;
  138. private Dictionary<string, JSONNode>.Enumerator m_Object;
  139. private List<JSONNode>.Enumerator m_Array;
  140. public bool IsValid { get { return type != Type.None; } }
  141. public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
  142. {
  143. type = Type.Array;
  144. m_Object = default(Dictionary<string, JSONNode>.Enumerator);
  145. m_Array = aArrayEnum;
  146. }
  147. public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
  148. {
  149. type = Type.Object;
  150. m_Object = aDictEnum;
  151. m_Array = default(List<JSONNode>.Enumerator);
  152. }
  153. public KeyValuePair<string, JSONNode> Current
  154. {
  155. get
  156. {
  157. if (type == Type.Array)
  158. return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
  159. else if (type == Type.Object)
  160. return m_Object.Current;
  161. return new KeyValuePair<string, JSONNode>(string.Empty, null);
  162. }
  163. }
  164. public bool MoveNext()
  165. {
  166. if (type == Type.Array)
  167. return m_Array.MoveNext();
  168. else if (type == Type.Object)
  169. return m_Object.MoveNext();
  170. return false;
  171. }
  172. }
  173. public struct ValueEnumerator
  174. {
  175. private Enumerator m_Enumerator;
  176. public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { }
  177. public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { }
  178. public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; }
  179. public JSONNode Current { get { return m_Enumerator.Current.Value; } }
  180. public bool MoveNext() { return m_Enumerator.MoveNext(); }
  181. public ValueEnumerator GetEnumerator() { return this; }
  182. }
  183. public struct KeyEnumerator
  184. {
  185. private Enumerator m_Enumerator;
  186. public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { }
  187. public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { }
  188. public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; }
  189. public JSONNode Current { get { return m_Enumerator.Current.Key; } }
  190. public bool MoveNext() { return m_Enumerator.MoveNext(); }
  191. public KeyEnumerator GetEnumerator() { return this; }
  192. }
  193. public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IEnumerable<KeyValuePair<string, JSONNode>>
  194. {
  195. private JSONNode m_Node;
  196. private Enumerator m_Enumerator;
  197. internal LinqEnumerator(JSONNode aNode)
  198. {
  199. m_Node = aNode;
  200. if (m_Node != null)
  201. m_Enumerator = m_Node.GetEnumerator();
  202. }
  203. public KeyValuePair<string, JSONNode> Current { get { return m_Enumerator.Current; } }
  204. object IEnumerator.Current { get { return m_Enumerator.Current; } }
  205. public bool MoveNext() { return m_Enumerator.MoveNext(); }
  206. public void Dispose()
  207. {
  208. m_Node = null;
  209. m_Enumerator = new Enumerator();
  210. }
  211. public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
  212. {
  213. return new LinqEnumerator(m_Node);
  214. }
  215. public void Reset()
  216. {
  217. if (m_Node != null)
  218. m_Enumerator = m_Node.GetEnumerator();
  219. }
  220. IEnumerator IEnumerable.GetEnumerator()
  221. {
  222. return new LinqEnumerator(m_Node);
  223. }
  224. }
  225. #endregion Enumerators
  226. #region common interface
  227. public static bool forceASCII = false; // Use Unicode by default
  228. public abstract JSONNodeType Tag { get; }
  229. public virtual JSONNode this[int aIndex] { get { return null; } set { } }
  230. public virtual JSONNode this[string aKey] { get { return null; } set { } }
  231. public virtual string Value { get { return ""; } set { } }
  232. public virtual int Count { get { return 0; } }
  233. public virtual bool IsNumber { get { return false; } }
  234. public virtual bool IsString { get { return false; } }
  235. public virtual bool IsBoolean { get { return false; } }
  236. public virtual bool IsNull { get { return false; } }
  237. public virtual bool IsArray { get { return false; } }
  238. public virtual bool IsObject { get { return false; } }
  239. public virtual bool Inline { get { return false; } set { } }
  240. public virtual void Add(string aKey, JSONNode aItem)
  241. {
  242. }
  243. public virtual void Add(JSONNode aItem)
  244. {
  245. Add("", aItem);
  246. }
  247. public virtual JSONNode Remove(string aKey)
  248. {
  249. return null;
  250. }
  251. public virtual JSONNode Remove(int aIndex)
  252. {
  253. return null;
  254. }
  255. public virtual JSONNode Remove(JSONNode aNode)
  256. {
  257. return aNode;
  258. }
  259. public virtual IEnumerable<JSONNode> Children
  260. {
  261. get
  262. {
  263. yield break;
  264. }
  265. }
  266. public IEnumerable<JSONNode> DeepChildren
  267. {
  268. get
  269. {
  270. foreach (var C in Children)
  271. foreach (var D in C.DeepChildren)
  272. yield return D;
  273. }
  274. }
  275. public override string ToString()
  276. {
  277. StringBuilder sb = new StringBuilder();
  278. WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact);
  279. return sb.ToString();
  280. }
  281. public virtual string ToString(int aIndent)
  282. {
  283. StringBuilder sb = new StringBuilder();
  284. WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent);
  285. return sb.ToString();
  286. }
  287. internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);
  288. public abstract Enumerator GetEnumerator();
  289. public IEnumerable<KeyValuePair<string, JSONNode>> Linq { get { return new LinqEnumerator(this); } }
  290. public KeyEnumerator Keys { get { return new KeyEnumerator(GetEnumerator()); } }
  291. public ValueEnumerator Values { get { return new ValueEnumerator(GetEnumerator()); } }
  292. #endregion common interface
  293. #region typecasting properties
  294. public virtual double AsDouble
  295. {
  296. get
  297. {
  298. double v = 0.0;
  299. if (double.TryParse(Value, out v))
  300. return v;
  301. return 0.0;
  302. }
  303. set
  304. {
  305. Value = value.ToString();
  306. }
  307. }
  308. public virtual int AsInt
  309. {
  310. get { return (int)AsDouble; }
  311. set { AsDouble = value; }
  312. }
  313. public virtual float AsFloat
  314. {
  315. get { return (float)AsDouble; }
  316. set { AsDouble = value; }
  317. }
  318. public virtual bool AsBool
  319. {
  320. get
  321. {
  322. bool v = false;
  323. if (bool.TryParse(Value, out v))
  324. return v;
  325. return !string.IsNullOrEmpty(Value);
  326. }
  327. set
  328. {
  329. Value = (value) ? "true" : "false";
  330. }
  331. }
  332. public virtual JSONArray AsArray
  333. {
  334. get
  335. {
  336. return this as JSONArray;
  337. }
  338. }
  339. public virtual JSONObject AsObject
  340. {
  341. get
  342. {
  343. return this as JSONObject;
  344. }
  345. }
  346. #endregion typecasting properties
  347. #region operators
  348. public static implicit operator JSONNode(string s)
  349. {
  350. return new JSONString(s);
  351. }
  352. public static implicit operator string(JSONNode d)
  353. {
  354. return (d == null) ? null : d.Value;
  355. }
  356. public static implicit operator JSONNode(double n)
  357. {
  358. return new JSONNumber(n);
  359. }
  360. public static implicit operator double(JSONNode d)
  361. {
  362. return (d == null) ? 0 : d.AsDouble;
  363. }
  364. public static implicit operator JSONNode(float n)
  365. {
  366. return new JSONNumber(n);
  367. }
  368. public static implicit operator float(JSONNode d)
  369. {
  370. return (d == null) ? 0 : d.AsFloat;
  371. }
  372. public static implicit operator JSONNode(int n)
  373. {
  374. return new JSONNumber(n);
  375. }
  376. public static implicit operator int(JSONNode d)
  377. {
  378. return (d == null) ? 0 : d.AsInt;
  379. }
  380. public static implicit operator JSONNode(bool b)
  381. {
  382. return new JSONBool(b);
  383. }
  384. public static implicit operator bool(JSONNode d)
  385. {
  386. return (d == null) ? false : d.AsBool;
  387. }
  388. public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
  389. {
  390. return aKeyValue.Value;
  391. }
  392. public static bool operator ==(JSONNode a, object b)
  393. {
  394. if (ReferenceEquals(a, b))
  395. return true;
  396. bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator;
  397. bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator;
  398. if (aIsNull && bIsNull)
  399. return true;
  400. return !aIsNull && a.Equals(b);
  401. }
  402. public static bool operator !=(JSONNode a, object b)
  403. {
  404. return !(a == b);
  405. }
  406. public override bool Equals(object obj)
  407. {
  408. return ReferenceEquals(this, obj);
  409. }
  410. public override int GetHashCode()
  411. {
  412. return base.GetHashCode();
  413. }
  414. #endregion operators
  415. [ThreadStatic]
  416. private static StringBuilder m_EscapeBuilder;
  417. internal static StringBuilder EscapeBuilder
  418. {
  419. get
  420. {
  421. if (m_EscapeBuilder == null)
  422. m_EscapeBuilder = new StringBuilder();
  423. return m_EscapeBuilder;
  424. }
  425. }
  426. internal static string Escape(string aText)
  427. {
  428. var sb = EscapeBuilder;
  429. sb.Length = 0;
  430. if (sb.Capacity < aText.Length + aText.Length / 10)
  431. sb.Capacity = aText.Length + aText.Length / 10;
  432. foreach (char c in aText)
  433. {
  434. switch (c)
  435. {
  436. case '\\':
  437. sb.Append("\\\\");
  438. break;
  439. case '\"':
  440. sb.Append("\\\"");
  441. break;
  442. case '\n':
  443. sb.Append("\\n");
  444. break;
  445. case '\r':
  446. sb.Append("\\r");
  447. break;
  448. case '\t':
  449. sb.Append("\\t");
  450. break;
  451. case '\b':
  452. sb.Append("\\b");
  453. break;
  454. case '\f':
  455. sb.Append("\\f");
  456. break;
  457. default:
  458. if (c < ' ' || (forceASCII && c > 127))
  459. {
  460. ushort val = c;
  461. sb.Append("\\u").Append(val.ToString("X4"));
  462. }
  463. else
  464. sb.Append(c);
  465. break;
  466. }
  467. }
  468. string result = sb.ToString();
  469. sb.Length = 0;
  470. return result;
  471. }
  472. static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted)
  473. {
  474. if (quoted)
  475. {
  476. ctx.Add(tokenName, token);
  477. return;
  478. }
  479. string tmp = token.ToLower();
  480. if (tmp == "false" || tmp == "true")
  481. ctx.Add(tokenName, tmp == "true");
  482. else if (tmp == "null")
  483. ctx.Add(tokenName, null);
  484. else
  485. {
  486. double val;
  487. if (double.TryParse(token, out val))
  488. ctx.Add(tokenName, val);
  489. else
  490. ctx.Add(tokenName, token);
  491. }
  492. }
  493. public static JSONNode Parse(string aJSON)
  494. {
  495. Stack<JSONNode> stack = new Stack<JSONNode>();
  496. JSONNode ctx = null;
  497. int i = 0;
  498. StringBuilder Token = new StringBuilder();
  499. string TokenName = "";
  500. bool QuoteMode = false;
  501. bool TokenIsQuoted = false;
  502. while (i < aJSON.Length)
  503. {
  504. switch (aJSON[i])
  505. {
  506. case '{':
  507. if (QuoteMode)
  508. {
  509. Token.Append(aJSON[i]);
  510. break;
  511. }
  512. stack.Push(new JSONObject());
  513. if (ctx != null)
  514. {
  515. ctx.Add(TokenName, stack.Peek());
  516. }
  517. TokenName = "";
  518. Token.Length = 0;
  519. ctx = stack.Peek();
  520. break;
  521. case '[':
  522. if (QuoteMode)
  523. {
  524. Token.Append(aJSON[i]);
  525. break;
  526. }
  527. stack.Push(new JSONArray());
  528. if (ctx != null)
  529. {
  530. ctx.Add(TokenName, stack.Peek());
  531. }
  532. TokenName = "";
  533. Token.Length = 0;
  534. ctx = stack.Peek();
  535. break;
  536. case '}':
  537. case ']':
  538. if (QuoteMode)
  539. {
  540. Token.Append(aJSON[i]);
  541. break;
  542. }
  543. if (stack.Count == 0)
  544. throw new Exception("JSON Parse: Too many closing brackets");
  545. stack.Pop();
  546. if (Token.Length > 0 || TokenIsQuoted)
  547. {
  548. ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted);
  549. TokenIsQuoted = false;
  550. }
  551. TokenName = "";
  552. Token.Length = 0;
  553. if (stack.Count > 0)
  554. ctx = stack.Peek();
  555. break;
  556. case ':':
  557. if (QuoteMode)
  558. {
  559. Token.Append(aJSON[i]);
  560. break;
  561. }
  562. TokenName = Token.ToString();
  563. Token.Length = 0;
  564. TokenIsQuoted = false;
  565. break;
  566. case '"':
  567. QuoteMode ^= true;
  568. TokenIsQuoted |= QuoteMode;
  569. break;
  570. case ',':
  571. if (QuoteMode)
  572. {
  573. Token.Append(aJSON[i]);
  574. break;
  575. }
  576. if (Token.Length > 0 || TokenIsQuoted)
  577. {
  578. ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted);
  579. TokenIsQuoted = false;
  580. }
  581. TokenName = "";
  582. Token.Length = 0;
  583. TokenIsQuoted = false;
  584. break;
  585. case '\r':
  586. case '\n':
  587. break;
  588. case ' ':
  589. case '\t':
  590. if (QuoteMode)
  591. Token.Append(aJSON[i]);
  592. break;
  593. case '\\':
  594. ++i;
  595. if (QuoteMode)
  596. {
  597. char C = aJSON[i];
  598. switch (C)
  599. {
  600. case 't':
  601. Token.Append('\t');
  602. break;
  603. case 'r':
  604. Token.Append('\r');
  605. break;
  606. case 'n':
  607. Token.Append('\n');
  608. break;
  609. case 'b':
  610. Token.Append('\b');
  611. break;
  612. case 'f':
  613. Token.Append('\f');
  614. break;
  615. case 'u':
  616. {
  617. string s = aJSON.Substring(i + 1, 4);
  618. Token.Append((char)int.Parse(
  619. s,
  620. System.Globalization.NumberStyles.AllowHexSpecifier));
  621. i += 4;
  622. break;
  623. }
  624. default:
  625. Token.Append(C);
  626. break;
  627. }
  628. }
  629. break;
  630. default:
  631. Token.Append(aJSON[i]);
  632. break;
  633. }
  634. ++i;
  635. }
  636. if (QuoteMode)
  637. {
  638. throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
  639. }
  640. return ctx;
  641. }
  642. }
  643. // End of JSONNode
  644. public partial class JSONArray : JSONNode
  645. {
  646. private List<JSONNode> m_List = new List<JSONNode>();
  647. private bool inline = false;
  648. public override bool Inline
  649. {
  650. get { return inline; }
  651. set { inline = value; }
  652. }
  653. public override JSONNodeType Tag { get { return JSONNodeType.Array; } }
  654. public override bool IsArray { get { return true; } }
  655. public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); }
  656. public override JSONNode this[int aIndex]
  657. {
  658. get
  659. {
  660. if (aIndex < 0 || aIndex >= m_List.Count)
  661. return new JSONLazyCreator(this);
  662. return m_List[aIndex];
  663. }
  664. set
  665. {
  666. if (value == null)
  667. value = JSONNull.CreateOrGet();
  668. if (aIndex < 0 || aIndex >= m_List.Count)
  669. m_List.Add(value);
  670. else
  671. m_List[aIndex] = value;
  672. }
  673. }
  674. public override JSONNode this[string aKey]
  675. {
  676. get { return new JSONLazyCreator(this); }
  677. set
  678. {
  679. if (value == null)
  680. value = JSONNull.CreateOrGet();
  681. m_List.Add(value);
  682. }
  683. }
  684. public override int Count
  685. {
  686. get { return m_List.Count; }
  687. }
  688. public override void Add(string aKey, JSONNode aItem)
  689. {
  690. if (aItem == null)
  691. aItem = JSONNull.CreateOrGet();
  692. m_List.Add(aItem);
  693. }
  694. public override JSONNode Remove(int aIndex)
  695. {
  696. if (aIndex < 0 || aIndex >= m_List.Count)
  697. return null;
  698. JSONNode tmp = m_List[aIndex];
  699. m_List.RemoveAt(aIndex);
  700. return tmp;
  701. }
  702. public override JSONNode Remove(JSONNode aNode)
  703. {
  704. m_List.Remove(aNode);
  705. return aNode;
  706. }
  707. public override IEnumerable<JSONNode> Children
  708. {
  709. get
  710. {
  711. foreach (JSONNode N in m_List)
  712. yield return N;
  713. }
  714. }
  715. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  716. {
  717. aSB.Append('[');
  718. int count = m_List.Count;
  719. if (inline)
  720. aMode = JSONTextMode.Compact;
  721. for (int i = 0; i < count; i++)
  722. {
  723. if (i > 0)
  724. aSB.Append(',');
  725. if (aMode == JSONTextMode.Indent)
  726. aSB.AppendLine();
  727. if (aMode == JSONTextMode.Indent)
  728. aSB.Append(' ', aIndent + aIndentInc);
  729. m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
  730. }
  731. if (aMode == JSONTextMode.Indent)
  732. aSB.AppendLine().Append(' ', aIndent);
  733. aSB.Append(']');
  734. }
  735. }
  736. // End of JSONArray
  737. public partial class JSONObject : JSONNode
  738. {
  739. private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();
  740. private bool inline = false;
  741. public override bool Inline
  742. {
  743. get { return inline; }
  744. set { inline = value; }
  745. }
  746. public override JSONNodeType Tag { get { return JSONNodeType.Object; } }
  747. public override bool IsObject { get { return true; } }
  748. public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); }
  749. public override JSONNode this[string aKey]
  750. {
  751. get
  752. {
  753. if (m_Dict.ContainsKey(aKey))
  754. return m_Dict[aKey];
  755. else
  756. return new JSONLazyCreator(this, aKey);
  757. }
  758. set
  759. {
  760. if (value == null)
  761. value = JSONNull.CreateOrGet();
  762. if (m_Dict.ContainsKey(aKey))
  763. m_Dict[aKey] = value;
  764. else
  765. m_Dict.Add(aKey, value);
  766. }
  767. }
  768. public override JSONNode this[int aIndex]
  769. {
  770. get
  771. {
  772. if (aIndex < 0 || aIndex >= m_Dict.Count)
  773. return null;
  774. return m_Dict.ElementAt(aIndex).Value;
  775. }
  776. set
  777. {
  778. if (value == null)
  779. value = JSONNull.CreateOrGet();
  780. if (aIndex < 0 || aIndex >= m_Dict.Count)
  781. return;
  782. string key = m_Dict.ElementAt(aIndex).Key;
  783. m_Dict[key] = value;
  784. }
  785. }
  786. public override int Count
  787. {
  788. get { return m_Dict.Count; }
  789. }
  790. public override void Add(string aKey, JSONNode aItem)
  791. {
  792. if (aItem == null)
  793. aItem = JSONNull.CreateOrGet();
  794. if (!string.IsNullOrEmpty(aKey))
  795. {
  796. if (m_Dict.ContainsKey(aKey))
  797. m_Dict[aKey] = aItem;
  798. else
  799. m_Dict.Add(aKey, aItem);
  800. }
  801. else
  802. m_Dict.Add(Guid.NewGuid().ToString(), aItem);
  803. }
  804. public override JSONNode Remove(string aKey)
  805. {
  806. if (!m_Dict.ContainsKey(aKey))
  807. return null;
  808. JSONNode tmp = m_Dict[aKey];
  809. m_Dict.Remove(aKey);
  810. return tmp;
  811. }
  812. public override JSONNode Remove(int aIndex)
  813. {
  814. if (aIndex < 0 || aIndex >= m_Dict.Count)
  815. return null;
  816. var item = m_Dict.ElementAt(aIndex);
  817. m_Dict.Remove(item.Key);
  818. return item.Value;
  819. }
  820. public override JSONNode Remove(JSONNode aNode)
  821. {
  822. try
  823. {
  824. var item = m_Dict.Where(k => k.Value == aNode).First();
  825. m_Dict.Remove(item.Key);
  826. return aNode;
  827. }
  828. catch
  829. {
  830. return null;
  831. }
  832. }
  833. public override IEnumerable<JSONNode> Children
  834. {
  835. get
  836. {
  837. foreach (KeyValuePair<string, JSONNode> N in m_Dict)
  838. yield return N.Value;
  839. }
  840. }
  841. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  842. {
  843. aSB.Append('{');
  844. bool first = true;
  845. if (inline)
  846. aMode = JSONTextMode.Compact;
  847. foreach (var k in m_Dict)
  848. {
  849. if (!first)
  850. aSB.Append(',');
  851. first = false;
  852. if (aMode == JSONTextMode.Indent)
  853. aSB.AppendLine();
  854. if (aMode == JSONTextMode.Indent)
  855. aSB.Append(' ', aIndent + aIndentInc);
  856. aSB.Append('\"').Append(Escape(k.Key)).Append('\"');
  857. if (aMode == JSONTextMode.Compact)
  858. aSB.Append(':');
  859. else
  860. aSB.Append(" : ");
  861. k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
  862. }
  863. if (aMode == JSONTextMode.Indent)
  864. aSB.AppendLine().Append(' ', aIndent);
  865. aSB.Append('}');
  866. }
  867. }
  868. // End of JSONObject
  869. public partial class JSONString : JSONNode
  870. {
  871. private string m_Data;
  872. public override JSONNodeType Tag { get { return JSONNodeType.String; } }
  873. public override bool IsString { get { return true; } }
  874. public override Enumerator GetEnumerator() { return new Enumerator(); }
  875. public override string Value
  876. {
  877. get { return m_Data; }
  878. set
  879. {
  880. m_Data = value;
  881. }
  882. }
  883. public JSONString(string aData)
  884. {
  885. m_Data = aData;
  886. }
  887. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  888. {
  889. aSB.Append('\"').Append(Escape(m_Data)).Append('\"');
  890. }
  891. public override bool Equals(object obj)
  892. {
  893. if (base.Equals(obj))
  894. return true;
  895. string s = obj as string;
  896. if (s != null)
  897. return m_Data == s;
  898. JSONString s2 = obj as JSONString;
  899. if (s2 != null)
  900. return m_Data == s2.m_Data;
  901. return false;
  902. }
  903. public override int GetHashCode()
  904. {
  905. return m_Data.GetHashCode();
  906. }
  907. }
  908. // End of JSONString
  909. public partial class JSONNumber : JSONNode
  910. {
  911. private double m_Data;
  912. public override JSONNodeType Tag { get { return JSONNodeType.Number; } }
  913. public override bool IsNumber { get { return true; } }
  914. public override Enumerator GetEnumerator() { return new Enumerator(); }
  915. public override string Value
  916. {
  917. get { return m_Data.ToString(); }
  918. set
  919. {
  920. double v;
  921. if (double.TryParse(value, out v))
  922. m_Data = v;
  923. }
  924. }
  925. public override double AsDouble
  926. {
  927. get { return m_Data; }
  928. set { m_Data = value; }
  929. }
  930. public JSONNumber(double aData)
  931. {
  932. m_Data = aData;
  933. }
  934. public JSONNumber(string aData)
  935. {
  936. Value = aData;
  937. }
  938. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  939. {
  940. aSB.Append(m_Data);
  941. }
  942. private static bool IsNumeric(object value)
  943. {
  944. return value is int || value is uint
  945. || value is float || value is double
  946. || value is decimal
  947. || value is long || value is ulong
  948. || value is short || value is ushort
  949. || value is sbyte || value is byte;
  950. }
  951. public override bool Equals(object obj)
  952. {
  953. if (obj == null)
  954. return false;
  955. if (base.Equals(obj))
  956. return true;
  957. JSONNumber s2 = obj as JSONNumber;
  958. if (s2 != null)
  959. return m_Data == s2.m_Data;
  960. if (IsNumeric(obj))
  961. return Convert.ToDouble(obj) == m_Data;
  962. return false;
  963. }
  964. public override int GetHashCode()
  965. {
  966. return m_Data.GetHashCode();
  967. }
  968. }
  969. // End of JSONNumber
  970. public partial class JSONBool : JSONNode
  971. {
  972. private bool m_Data;
  973. public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } }
  974. public override bool IsBoolean { get { return true; } }
  975. public override Enumerator GetEnumerator() { return new Enumerator(); }
  976. public override string Value
  977. {
  978. get { return m_Data.ToString(); }
  979. set
  980. {
  981. bool v;
  982. if (bool.TryParse(value, out v))
  983. m_Data = v;
  984. }
  985. }
  986. public override bool AsBool
  987. {
  988. get { return m_Data; }
  989. set { m_Data = value; }
  990. }
  991. public JSONBool(bool aData)
  992. {
  993. m_Data = aData;
  994. }
  995. public JSONBool(string aData)
  996. {
  997. Value = aData;
  998. }
  999. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  1000. {
  1001. aSB.Append((m_Data) ? "true" : "false");
  1002. }
  1003. public override bool Equals(object obj)
  1004. {
  1005. if (obj == null)
  1006. return false;
  1007. if (obj is bool)
  1008. return m_Data == (bool)obj;
  1009. return false;
  1010. }
  1011. public override int GetHashCode()
  1012. {
  1013. return m_Data.GetHashCode();
  1014. }
  1015. }
  1016. // End of JSONBool
  1017. public partial class JSONNull : JSONNode
  1018. {
  1019. static JSONNull m_StaticInstance = new JSONNull();
  1020. public static bool reuseSameInstance = true;
  1021. public static JSONNull CreateOrGet()
  1022. {
  1023. if (reuseSameInstance)
  1024. return m_StaticInstance;
  1025. return new JSONNull();
  1026. }
  1027. private JSONNull() { }
  1028. public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } }
  1029. public override bool IsNull { get { return true; } }
  1030. public override Enumerator GetEnumerator() { return new Enumerator(); }
  1031. public override string Value
  1032. {
  1033. get { return "null"; }
  1034. set { }
  1035. }
  1036. public override bool AsBool
  1037. {
  1038. get { return false; }
  1039. set { }
  1040. }
  1041. public override bool Equals(object obj)
  1042. {
  1043. if (object.ReferenceEquals(this, obj))
  1044. return true;
  1045. return (obj is JSONNull);
  1046. }
  1047. public override int GetHashCode()
  1048. {
  1049. return 0;
  1050. }
  1051. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  1052. {
  1053. aSB.Append("null");
  1054. }
  1055. }
  1056. // End of JSONNull
  1057. internal partial class JSONLazyCreator : JSONNode
  1058. {
  1059. private JSONNode m_Node = null;
  1060. private string m_Key = null;
  1061. public override JSONNodeType Tag { get { return JSONNodeType.None; } }
  1062. public override Enumerator GetEnumerator() { return new Enumerator(); }
  1063. public JSONLazyCreator(JSONNode aNode)
  1064. {
  1065. m_Node = aNode;
  1066. m_Key = null;
  1067. }
  1068. public JSONLazyCreator(JSONNode aNode, string aKey)
  1069. {
  1070. m_Node = aNode;
  1071. m_Key = aKey;
  1072. }
  1073. private void Set(JSONNode aVal)
  1074. {
  1075. if (m_Key == null)
  1076. {
  1077. m_Node.Add(aVal);
  1078. }
  1079. else
  1080. {
  1081. m_Node.Add(m_Key, aVal);
  1082. }
  1083. m_Node = null; // Be GC friendly.
  1084. }
  1085. public override JSONNode this[int aIndex]
  1086. {
  1087. get
  1088. {
  1089. return new JSONLazyCreator(this);
  1090. }
  1091. set
  1092. {
  1093. var tmp = new JSONArray();
  1094. tmp.Add(value);
  1095. Set(tmp);
  1096. }
  1097. }
  1098. public override JSONNode this[string aKey]
  1099. {
  1100. get
  1101. {
  1102. return new JSONLazyCreator(this, aKey);
  1103. }
  1104. set
  1105. {
  1106. var tmp = new JSONObject();
  1107. tmp.Add(aKey, value);
  1108. Set(tmp);
  1109. }
  1110. }
  1111. public override void Add(JSONNode aItem)
  1112. {
  1113. var tmp = new JSONArray();
  1114. tmp.Add(aItem);
  1115. Set(tmp);
  1116. }
  1117. public override void Add(string aKey, JSONNode aItem)
  1118. {
  1119. var tmp = new JSONObject();
  1120. tmp.Add(aKey, aItem);
  1121. Set(tmp);
  1122. }
  1123. public static bool operator ==(JSONLazyCreator a, object b)
  1124. {
  1125. if (b == null)
  1126. return true;
  1127. return System.Object.ReferenceEquals(a, b);
  1128. }
  1129. public static bool operator !=(JSONLazyCreator a, object b)
  1130. {
  1131. return !(a == b);
  1132. }
  1133. public override bool Equals(object obj)
  1134. {
  1135. if (obj == null)
  1136. return true;
  1137. return System.Object.ReferenceEquals(this, obj);
  1138. }
  1139. public override int GetHashCode()
  1140. {
  1141. return 0;
  1142. }
  1143. public override int AsInt
  1144. {
  1145. get
  1146. {
  1147. JSONNumber tmp = new JSONNumber(0);
  1148. Set(tmp);
  1149. return 0;
  1150. }
  1151. set
  1152. {
  1153. JSONNumber tmp = new JSONNumber(value);
  1154. Set(tmp);
  1155. }
  1156. }
  1157. public override float AsFloat
  1158. {
  1159. get
  1160. {
  1161. JSONNumber tmp = new JSONNumber(0.0f);
  1162. Set(tmp);
  1163. return 0.0f;
  1164. }
  1165. set
  1166. {
  1167. JSONNumber tmp = new JSONNumber(value);
  1168. Set(tmp);
  1169. }
  1170. }
  1171. public override double AsDouble
  1172. {
  1173. get
  1174. {
  1175. JSONNumber tmp = new JSONNumber(0.0);
  1176. Set(tmp);
  1177. return 0.0;
  1178. }
  1179. set
  1180. {
  1181. JSONNumber tmp = new JSONNumber(value);
  1182. Set(tmp);
  1183. }
  1184. }
  1185. public override bool AsBool
  1186. {
  1187. get
  1188. {
  1189. JSONBool tmp = new JSONBool(false);
  1190. Set(tmp);
  1191. return false;
  1192. }
  1193. set
  1194. {
  1195. JSONBool tmp = new JSONBool(value);
  1196. Set(tmp);
  1197. }
  1198. }
  1199. public override JSONArray AsArray
  1200. {
  1201. get
  1202. {
  1203. JSONArray tmp = new JSONArray();
  1204. Set(tmp);
  1205. return tmp;
  1206. }
  1207. }
  1208. public override JSONObject AsObject
  1209. {
  1210. get
  1211. {
  1212. JSONObject tmp = new JSONObject();
  1213. Set(tmp);
  1214. return tmp;
  1215. }
  1216. }
  1217. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  1218. {
  1219. aSB.Append("null");
  1220. }
  1221. }
  1222. // End of JSONLazyCreator
  1223. public static class JSON
  1224. {
  1225. public static JSONNode Parse(string aJSON)
  1226. {
  1227. return JSONNode.Parse(aJSON);
  1228. }
  1229. }
  1230. }