SimpleJSON.cs 45 KB

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