SimpleJSON.cs 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  1. //#define USE_SharpZipLib
  2. #if !UNITY_WEBPLAYER && !NETFX_CORE
  3. #define USE_FileIO
  4. #endif
  5. //#define DISABLE_LINQ_EXT
  6. /* * * * *
  7. * A simple JSON Parser / builder
  8. * ------------------------------
  9. *
  10. * It mainly has been written as a simple JSON parser. It can build a JSON string
  11. * from the node-tree, or generate a node tree from any valid JSON string.
  12. *
  13. * If you want to use compression when saving to file / stream / B64 you have to include
  14. * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
  15. * define "USE_SharpZipLib" at the top of the file
  16. *
  17. * Written by Bunny83
  18. * 2012-06-09
  19. *
  20. * Features / attributes:
  21. * - provides strongly typed node classes and lists / dictionaries
  22. * - provides easy access to class members / array items / data values
  23. * - the parser ignores data types. Each value is a string.
  24. * - only double quotes (") are used for quoting strings.
  25. * - values and names are not restricted to quoted strings. They simply add up and are trimmed.
  26. * - There are only 3 types: arrays(JSONArray), objects(JSONClass) and values(JSONData)
  27. * - provides "casting" properties to easily convert to / from those types:
  28. * int / float / double / bool
  29. * - provides a common interface for each node so no explicit casting is required.
  30. * - the parser try to avoid errors, but if malformed JSON is parsed the result is undefined
  31. *
  32. *
  33. * 2012-12-17 Update:
  34. * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
  35. * Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
  36. * The class determines the required type by it's further use, creates the type and removes itself.
  37. * - Added binary serialization / deserialization.
  38. * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
  39. * The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
  40. * - The serializer uses different types when it comes to store the values. Since my data values
  41. * are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
  42. * It's not the most efficient way but for a moderate amount of data it should work on all platforms.
  43. *
  44. * * * * */
  45. using System;
  46. using System.Collections;
  47. using System.Collections.Generic;
  48. using System.Globalization;
  49. using System.IO;
  50. using System.Linq;
  51. namespace I2.Loc.SimpleJSON
  52. {
  53. public enum JSONBinaryTag
  54. {
  55. Array = 1,
  56. Class = 2,
  57. Value = 3,
  58. IntValue = 4,
  59. DoubleValue = 5,
  60. BoolValue = 6,
  61. FloatValue = 7
  62. }
  63. public class JSONNode
  64. {
  65. #region common interface
  66. public virtual void Add(string aKey, JSONNode aItem){ }
  67. public virtual JSONNode this[int aIndex] { get { return null; } set { } }
  68. public virtual JSONNode this[string aKey] { get { return null; } set { } }
  69. public virtual string Value { get { return ""; } set { } }
  70. public virtual int Count { get { return 0; } }
  71. public virtual void Add(JSONNode aItem)
  72. {
  73. Add("", aItem);
  74. }
  75. public virtual JSONNode Remove(string aKey) { return null; }
  76. public virtual JSONNode Remove(int aIndex) { return null; }
  77. public virtual JSONNode Remove(JSONNode aNode) { return aNode; }
  78. public virtual IEnumerable<JSONNode> Childs { get { yield break;} }
  79. public IEnumerable<JSONNode> DeepChilds
  80. {
  81. get
  82. {
  83. foreach (var C in Childs)
  84. foreach (var D in C.DeepChilds)
  85. yield return D;
  86. }
  87. }
  88. public override string ToString()
  89. {
  90. return "JSONNode";
  91. }
  92. public virtual string ToString(string aPrefix)
  93. {
  94. return "JSONNode";
  95. }
  96. #endregion common interface
  97. #region typecasting properties
  98. public virtual int AsInt
  99. {
  100. get
  101. {
  102. int v = 0;
  103. if (int.TryParse(Value,out v))
  104. return v;
  105. return 0;
  106. }
  107. set
  108. {
  109. Value = value.ToString();
  110. }
  111. }
  112. public virtual float AsFloat
  113. {
  114. get
  115. {
  116. float v = 0.0f;
  117. if (float.TryParse(Value,out v))
  118. return v;
  119. return 0.0f;
  120. }
  121. set
  122. {
  123. Value = value.ToString();
  124. }
  125. }
  126. public virtual double AsDouble
  127. {
  128. get
  129. {
  130. double v = 0.0;
  131. if (double.TryParse(Value,out v))
  132. return v;
  133. return 0.0;
  134. }
  135. set
  136. {
  137. Value = value.ToString();
  138. }
  139. }
  140. public virtual bool AsBool
  141. {
  142. get
  143. {
  144. bool v = false;
  145. if (bool.TryParse(Value,out v))
  146. return v;
  147. return !string.IsNullOrEmpty(Value);
  148. }
  149. set
  150. {
  151. Value = value?"true":"false";
  152. }
  153. }
  154. public virtual JSONArray AsArray
  155. {
  156. get
  157. {
  158. return this as JSONArray;
  159. }
  160. }
  161. public virtual JSONClass AsObject
  162. {
  163. get
  164. {
  165. return this as JSONClass;
  166. }
  167. }
  168. #endregion typecasting properties
  169. #region operators
  170. public static implicit operator JSONNode(string s)
  171. {
  172. return new JSONData(s);
  173. }
  174. public static implicit operator string(JSONNode d)
  175. {
  176. return d == null?null:d.Value;
  177. }
  178. public static bool operator ==(JSONNode a, object b)
  179. {
  180. if (b == null && a is JSONLazyCreator)
  181. return true;
  182. return ReferenceEquals(a,b);
  183. }
  184. public static bool operator !=(JSONNode a, object b)
  185. {
  186. return !(a == b);
  187. }
  188. public override bool Equals (object obj)
  189. {
  190. return ReferenceEquals(this, obj);
  191. }
  192. public override int GetHashCode ()
  193. {
  194. return base.GetHashCode();
  195. }
  196. #endregion operators
  197. internal static string Escape(string aText)
  198. {
  199. string result = "";
  200. foreach(char c in aText)
  201. {
  202. switch(c)
  203. {
  204. case '\\' : result += "\\\\"; break;
  205. case '\"' : result += "\\\""; break;
  206. case '\n' : result += "\\n" ; break;
  207. case '\r' : result += "\\r" ; break;
  208. case '\t' : result += "\\t" ; break;
  209. case '\b' : result += "\\b" ; break;
  210. case '\f' : result += "\\f" ; break;
  211. default : result += c ; break;
  212. }
  213. }
  214. return result;
  215. }
  216. public static JSONNode Parse(string aJSON)
  217. {
  218. Stack<JSONNode> stack = new Stack<JSONNode>();
  219. JSONNode ctx = null;
  220. int i = 0;
  221. string Token = "";
  222. string TokenName = "";
  223. bool QuoteMode = false;
  224. while (i < aJSON.Length)
  225. {
  226. switch (aJSON[i])
  227. {
  228. case '{':
  229. if (QuoteMode)
  230. {
  231. Token += aJSON[i];
  232. break;
  233. }
  234. stack.Push(new JSONClass());
  235. if (ctx != null)
  236. {
  237. TokenName = TokenName.Trim();
  238. if (ctx is JSONArray)
  239. ctx.Add(stack.Peek());
  240. else if (TokenName != "")
  241. ctx.Add(TokenName,stack.Peek());
  242. }
  243. TokenName = "";
  244. Token = "";
  245. ctx = stack.Peek();
  246. break;
  247. case '[':
  248. if (QuoteMode)
  249. {
  250. Token += aJSON[i];
  251. break;
  252. }
  253. stack.Push(new JSONArray());
  254. if (ctx != null)
  255. {
  256. TokenName = TokenName.Trim();
  257. if (ctx is JSONArray)
  258. ctx.Add(stack.Peek());
  259. else if (TokenName != "")
  260. ctx.Add(TokenName,stack.Peek());
  261. }
  262. TokenName = "";
  263. Token = "";
  264. ctx = stack.Peek();
  265. break;
  266. case '}':
  267. case ']':
  268. if (QuoteMode)
  269. {
  270. Token += aJSON[i];
  271. break;
  272. }
  273. if (stack.Count == 0)
  274. throw new Exception("JSON Parse: Too many closing brackets");
  275. stack.Pop();
  276. if (Token != "")
  277. {
  278. TokenName = TokenName.Trim();
  279. if (ctx is JSONArray)
  280. ctx.Add(Token);
  281. else if (TokenName != "")
  282. ctx.Add(TokenName,Token);
  283. }
  284. TokenName = "";
  285. Token = "";
  286. if (stack.Count>0)
  287. ctx = stack.Peek();
  288. break;
  289. case ':':
  290. if (QuoteMode)
  291. {
  292. Token += aJSON[i];
  293. break;
  294. }
  295. TokenName = Token;
  296. Token = "";
  297. break;
  298. case '"':
  299. QuoteMode ^= true;
  300. break;
  301. case ',':
  302. if (QuoteMode)
  303. {
  304. Token += aJSON[i];
  305. break;
  306. }
  307. if (Token != "")
  308. {
  309. if (ctx is JSONArray)
  310. ctx.Add(Token);
  311. else if (TokenName != "")
  312. ctx.Add(TokenName, Token);
  313. }
  314. TokenName = "";
  315. Token = "";
  316. break;
  317. case '\r':
  318. case '\n':
  319. break;
  320. case ' ':
  321. case '\t':
  322. if (QuoteMode)
  323. Token += aJSON[i];
  324. break;
  325. case '\\':
  326. ++i;
  327. if (QuoteMode)
  328. {
  329. char C = aJSON[i];
  330. switch (C)
  331. {
  332. case 't' : Token += '\t'; break;
  333. case 'r' : Token += '\r'; break;
  334. case 'n' : Token += '\n'; break;
  335. case 'b' : Token += '\b'; break;
  336. case 'f' : Token += '\f'; break;
  337. case 'u':
  338. {
  339. string s = aJSON.Substring(i+1,4);
  340. Token += (char)int.Parse(s, NumberStyles.AllowHexSpecifier);
  341. i += 4;
  342. break;
  343. }
  344. default : Token += C; break;
  345. }
  346. }
  347. break;
  348. default:
  349. Token += aJSON[i];
  350. break;
  351. }
  352. ++i;
  353. }
  354. if (QuoteMode)
  355. {
  356. throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
  357. }
  358. return ctx;
  359. }
  360. public virtual void Serialize(BinaryWriter aWriter) {}
  361. public void SaveToStream(Stream aData)
  362. {
  363. var W = new BinaryWriter(aData);
  364. Serialize(W);
  365. }
  366. #if USE_SharpZipLib
  367. public void SaveToCompressedStream(System.IO.Stream aData)
  368. {
  369. using (var gzipOut = new ICSharpCode.SharpZipLib.BZip2.BZip2OutputStream(aData))
  370. {
  371. gzipOut.IsStreamOwner = false;
  372. SaveToStream(gzipOut);
  373. gzipOut.Close();
  374. }
  375. }
  376. public void SaveToCompressedFile(string aFileName)
  377. {
  378. #if USE_FileIO
  379. System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
  380. using(var F = System.IO.File.OpenWrite(aFileName))
  381. {
  382. SaveToCompressedStream(F);
  383. }
  384. #else
  385. throw new Exception("Can't use File IO stuff in webplayer");
  386. #endif
  387. }
  388. public string SaveToCompressedBase64()
  389. {
  390. using (var stream = new System.IO.MemoryStream())
  391. {
  392. SaveToCompressedStream(stream);
  393. stream.Position = 0;
  394. return System.Convert.ToBase64String(stream.ToArray());
  395. }
  396. }
  397. #else
  398. public void SaveToCompressedStream(Stream aData)
  399. {
  400. throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
  401. }
  402. public void SaveToCompressedFile(string aFileName)
  403. {
  404. throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
  405. }
  406. public string SaveToCompressedBase64()
  407. {
  408. throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
  409. }
  410. #endif
  411. public void SaveToFile(string aFileName)
  412. {
  413. #if USE_FileIO
  414. Directory.CreateDirectory(new FileInfo(aFileName).Directory.FullName);
  415. using(var F = File.OpenWrite(aFileName))
  416. {
  417. SaveToStream(F);
  418. }
  419. #else
  420. throw new Exception("Can't use File IO stuff in webplayer");
  421. #endif
  422. }
  423. public string SaveToBase64()
  424. {
  425. using (var stream = new MemoryStream())
  426. {
  427. SaveToStream(stream);
  428. stream.Position = 0;
  429. return Convert.ToBase64String(stream.ToArray());
  430. }
  431. }
  432. public static JSONNode Deserialize(BinaryReader aReader)
  433. {
  434. JSONBinaryTag type = (JSONBinaryTag)aReader.ReadByte();
  435. switch(type)
  436. {
  437. case JSONBinaryTag.Array:
  438. {
  439. int count = aReader.ReadInt32();
  440. JSONArray tmp = new JSONArray();
  441. for(int i = 0; i < count; i++)
  442. tmp.Add(Deserialize(aReader));
  443. return tmp;
  444. }
  445. case JSONBinaryTag.Class:
  446. {
  447. int count = aReader.ReadInt32();
  448. JSONClass tmp = new JSONClass();
  449. for(int i = 0; i < count; i++)
  450. {
  451. string key = aReader.ReadString();
  452. var val = Deserialize(aReader);
  453. tmp.Add(key, val);
  454. }
  455. return tmp;
  456. }
  457. case JSONBinaryTag.Value:
  458. {
  459. return new JSONData(aReader.ReadString());
  460. }
  461. case JSONBinaryTag.IntValue:
  462. {
  463. return new JSONData(aReader.ReadInt32());
  464. }
  465. case JSONBinaryTag.DoubleValue:
  466. {
  467. return new JSONData(aReader.ReadDouble());
  468. }
  469. case JSONBinaryTag.BoolValue:
  470. {
  471. return new JSONData(aReader.ReadBoolean());
  472. }
  473. case JSONBinaryTag.FloatValue:
  474. {
  475. return new JSONData(aReader.ReadSingle());
  476. }
  477. default:
  478. {
  479. throw new Exception("Error deserializing JSON. Unknown tag: " + type);
  480. }
  481. }
  482. }
  483. #if USE_SharpZipLib
  484. public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
  485. {
  486. var zin = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(aData);
  487. return LoadFromStream(zin);
  488. }
  489. public static JSONNode LoadFromCompressedFile(string aFileName)
  490. {
  491. #if USE_FileIO
  492. using(var F = System.IO.File.OpenRead(aFileName))
  493. {
  494. return LoadFromCompressedStream(F);
  495. }
  496. #else
  497. throw new Exception("Can't use File IO stuff in webplayer");
  498. #endif
  499. }
  500. public static JSONNode LoadFromCompressedBase64(string aBase64)
  501. {
  502. var tmp = System.Convert.FromBase64String(aBase64);
  503. var stream = new System.IO.MemoryStream(tmp);
  504. stream.Position = 0;
  505. return LoadFromCompressedStream(stream);
  506. }
  507. #else
  508. public static JSONNode LoadFromCompressedFile(string aFileName)
  509. {
  510. throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
  511. }
  512. public static JSONNode LoadFromCompressedStream(Stream aData)
  513. {
  514. throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
  515. }
  516. public static JSONNode LoadFromCompressedBase64(string aBase64)
  517. {
  518. throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
  519. }
  520. #endif
  521. public static JSONNode LoadFromStream(Stream aData)
  522. {
  523. using(var R = new BinaryReader(aData))
  524. {
  525. return Deserialize(R);
  526. }
  527. }
  528. public static JSONNode LoadFromFile(string aFileName)
  529. {
  530. #if USE_FileIO
  531. using(var F = File.OpenRead(aFileName))
  532. {
  533. return LoadFromStream(F);
  534. }
  535. #else
  536. throw new Exception("Can't use File IO stuff in webplayer");
  537. #endif
  538. }
  539. public static JSONNode LoadFromBase64(string aBase64)
  540. {
  541. var tmp = Convert.FromBase64String(aBase64);
  542. var stream = new MemoryStream(tmp);
  543. stream.Position = 0;
  544. return LoadFromStream(stream);
  545. }
  546. } // End of JSONNode
  547. public class JSONArray : JSONNode, IEnumerable
  548. {
  549. private List<JSONNode> m_List = new List<JSONNode>();
  550. public override JSONNode this[int aIndex]
  551. {
  552. get
  553. {
  554. if (aIndex<0 || aIndex >= m_List.Count)
  555. return new JSONLazyCreator(this);
  556. return m_List[aIndex];
  557. }
  558. set
  559. {
  560. if (aIndex<0 || aIndex >= m_List.Count)
  561. m_List.Add(value);
  562. else
  563. m_List[aIndex] = value;
  564. }
  565. }
  566. public override JSONNode this[string aKey]
  567. {
  568. get{ return new JSONLazyCreator(this);}
  569. set{ m_List.Add(value); }
  570. }
  571. public override int Count
  572. {
  573. get { return m_List.Count; }
  574. }
  575. public override void Add(string aKey, JSONNode aItem)
  576. {
  577. m_List.Add(aItem);
  578. }
  579. public override JSONNode Remove(int aIndex)
  580. {
  581. if (aIndex < 0 || aIndex >= m_List.Count)
  582. return null;
  583. JSONNode tmp = m_List[aIndex];
  584. m_List.RemoveAt(aIndex);
  585. return tmp;
  586. }
  587. public override JSONNode Remove(JSONNode aNode)
  588. {
  589. m_List.Remove(aNode);
  590. return aNode;
  591. }
  592. public override IEnumerable<JSONNode> Childs
  593. {
  594. get
  595. {
  596. foreach(JSONNode N in m_List)
  597. yield return N;
  598. }
  599. }
  600. public IEnumerator GetEnumerator()
  601. {
  602. foreach(JSONNode N in m_List)
  603. yield return N;
  604. }
  605. public override string ToString()
  606. {
  607. string result = "[ ";
  608. foreach (JSONNode N in m_List)
  609. {
  610. if (result.Length > 2)
  611. result += ", ";
  612. result += N.ToString();
  613. }
  614. result += " ]";
  615. return result;
  616. }
  617. public override string ToString(string aPrefix)
  618. {
  619. string result = "[ ";
  620. foreach (JSONNode N in m_List)
  621. {
  622. if (result.Length > 3)
  623. result += ", ";
  624. result += "\n" + aPrefix + " ";
  625. result += N.ToString(aPrefix+" ");
  626. }
  627. result += "\n" + aPrefix + "]";
  628. return result;
  629. }
  630. public override void Serialize (BinaryWriter aWriter)
  631. {
  632. aWriter.Write((byte)JSONBinaryTag.Array);
  633. aWriter.Write(m_List.Count);
  634. for(int i = 0; i < m_List.Count; i++)
  635. {
  636. m_List[i].Serialize(aWriter);
  637. }
  638. }
  639. } // End of JSONArray
  640. public class JSONClass : JSONNode, IEnumerable
  641. {
  642. private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(StringComparer.Ordinal);
  643. public override JSONNode this[string aKey]
  644. {
  645. get
  646. {
  647. if (m_Dict.ContainsKey(aKey))
  648. return m_Dict[aKey];
  649. return new JSONLazyCreator(this, aKey);
  650. }
  651. set
  652. {
  653. if (m_Dict.ContainsKey(aKey))
  654. m_Dict[aKey] = value;
  655. else
  656. m_Dict.Add(aKey,value);
  657. }
  658. }
  659. public override JSONNode this[int aIndex]
  660. {
  661. get
  662. {
  663. if (aIndex < 0 || aIndex >= m_Dict.Count)
  664. return null;
  665. #if DISABLE_LINQ_EXT
  666. foreach (var kvp in m_Dict)
  667. {
  668. if (aIndex==0)
  669. return kvp.Value;
  670. aIndex--;
  671. }
  672. return null;
  673. #else
  674. return m_Dict.ElementAt(aIndex).Value;
  675. #endif
  676. }
  677. set
  678. {
  679. if (aIndex < 0 || aIndex >= m_Dict.Count)
  680. return;
  681. #if DISABLE_LINQ_EXT
  682. string[] keys = new string[m_Dict.Keys.Count];
  683. m_Dict.Keys.CopyTo(keys,0);
  684. string key = keys[aIndex];
  685. #else
  686. string key = m_Dict.ElementAt(aIndex).Key;
  687. #endif
  688. m_Dict[key] = value;
  689. }
  690. }
  691. public override int Count
  692. {
  693. get { return m_Dict.Count; }
  694. }
  695. public override void Add(string aKey, JSONNode aItem)
  696. {
  697. if (!string.IsNullOrEmpty(aKey))
  698. {
  699. if (m_Dict.ContainsKey(aKey))
  700. m_Dict[aKey] = aItem;
  701. else
  702. m_Dict.Add(aKey, aItem);
  703. }
  704. else
  705. m_Dict.Add(Guid.NewGuid().ToString(), aItem);
  706. }
  707. public override JSONNode Remove(string aKey)
  708. {
  709. if (!m_Dict.ContainsKey(aKey))
  710. return null;
  711. JSONNode tmp = m_Dict[aKey];
  712. m_Dict.Remove(aKey);
  713. return tmp;
  714. }
  715. public override JSONNode Remove(int aIndex)
  716. {
  717. if (aIndex < 0 || aIndex >= m_Dict.Count)
  718. return null;
  719. #if DISABLE_LINQ_EXT
  720. string[] keys = new string[m_Dict.Keys.Count];
  721. m_Dict.Keys.CopyTo(keys,0);
  722. string key = keys[aIndex];
  723. var value = m_Dict[key];
  724. m_Dict.Remove(key);
  725. return value;
  726. #else
  727. var item = m_Dict.ElementAt(aIndex);
  728. m_Dict.Remove(item.Key);
  729. return item.Value;
  730. #endif
  731. }
  732. public override JSONNode Remove(JSONNode aNode)
  733. {
  734. try
  735. {
  736. #if DISABLE_LINQ_EXT
  737. foreach (var kvp in m_Dict)
  738. if (kvp.Value == aNode)
  739. {
  740. m_Dict.Remove(kvp.Key);
  741. break;
  742. }
  743. return aNode;
  744. #else
  745. var item = m_Dict.Where(k => k.Value == aNode).First();
  746. m_Dict.Remove(item.Key);
  747. return aNode;
  748. #endif
  749. }
  750. catch
  751. {
  752. return null;
  753. }
  754. }
  755. public override IEnumerable<JSONNode> Childs
  756. {
  757. get
  758. {
  759. foreach(KeyValuePair<string,JSONNode> N in m_Dict)
  760. yield return N.Value;
  761. }
  762. }
  763. public IEnumerator GetEnumerator()
  764. {
  765. foreach(KeyValuePair<string, JSONNode> N in m_Dict)
  766. yield return N;
  767. }
  768. public override string ToString()
  769. {
  770. string result = "{";
  771. foreach (KeyValuePair<string, JSONNode> N in m_Dict)
  772. {
  773. if (result.Length > 2)
  774. result += ", ";
  775. result += "\"" + Escape(N.Key) + "\":" + N.Value;
  776. }
  777. result += "}";
  778. return result;
  779. }
  780. public override string ToString(string aPrefix)
  781. {
  782. string result = "{ ";
  783. foreach (KeyValuePair<string, JSONNode> N in m_Dict)
  784. {
  785. if (result.Length > 3)
  786. result += ", ";
  787. result += "\n" + aPrefix + " ";
  788. result += "\"" + Escape(N.Key) + "\" : " + N.Value.ToString(aPrefix+" ");
  789. }
  790. result += "\n" + aPrefix + "}";
  791. return result;
  792. }
  793. public override void Serialize (BinaryWriter aWriter)
  794. {
  795. aWriter.Write((byte)JSONBinaryTag.Class);
  796. aWriter.Write(m_Dict.Count);
  797. foreach(string K in m_Dict.Keys)
  798. {
  799. aWriter.Write(K);
  800. m_Dict[K].Serialize(aWriter);
  801. }
  802. }
  803. } // End of JSONClass
  804. public class JSONData : JSONNode
  805. {
  806. private string m_Data;
  807. public override string Value
  808. {
  809. get { return m_Data; }
  810. set { m_Data = value; }
  811. }
  812. public JSONData(string aData)
  813. {
  814. m_Data = aData;
  815. }
  816. public JSONData(float aData)
  817. {
  818. AsFloat = aData;
  819. }
  820. public JSONData(double aData)
  821. {
  822. AsDouble = aData;
  823. }
  824. public JSONData(bool aData)
  825. {
  826. AsBool = aData;
  827. }
  828. public JSONData(int aData)
  829. {
  830. AsInt = aData;
  831. }
  832. public override string ToString()
  833. {
  834. return "\"" + Escape(m_Data) + "\"";
  835. }
  836. public override string ToString(string aPrefix)
  837. {
  838. return "\"" + Escape(m_Data) + "\"";
  839. }
  840. public override void Serialize (BinaryWriter aWriter)
  841. {
  842. var tmp = new JSONData("");
  843. tmp.AsInt = AsInt;
  844. if (tmp.m_Data == m_Data)
  845. {
  846. aWriter.Write((byte)JSONBinaryTag.IntValue);
  847. aWriter.Write(AsInt);
  848. return;
  849. }
  850. tmp.AsFloat = AsFloat;
  851. if (tmp.m_Data == m_Data)
  852. {
  853. aWriter.Write((byte)JSONBinaryTag.FloatValue);
  854. aWriter.Write(AsFloat);
  855. return;
  856. }
  857. tmp.AsDouble = AsDouble;
  858. if (tmp.m_Data == m_Data)
  859. {
  860. aWriter.Write((byte)JSONBinaryTag.DoubleValue);
  861. aWriter.Write(AsDouble);
  862. return;
  863. }
  864. tmp.AsBool = AsBool;
  865. if (tmp.m_Data == m_Data)
  866. {
  867. aWriter.Write((byte)JSONBinaryTag.BoolValue);
  868. aWriter.Write(AsBool);
  869. return;
  870. }
  871. aWriter.Write((byte)JSONBinaryTag.Value);
  872. aWriter.Write(m_Data);
  873. }
  874. } // End of JSONData
  875. internal class JSONLazyCreator : JSONNode
  876. {
  877. private JSONNode m_Node;
  878. private string m_Key;
  879. public JSONLazyCreator(JSONNode aNode)
  880. {
  881. m_Node = aNode;
  882. m_Key = null;
  883. }
  884. public JSONLazyCreator(JSONNode aNode, string aKey)
  885. {
  886. m_Node = aNode;
  887. m_Key = aKey;
  888. }
  889. private void Set(JSONNode aVal)
  890. {
  891. if (m_Key == null)
  892. {
  893. m_Node.Add(aVal);
  894. }
  895. else
  896. {
  897. m_Node.Add(m_Key, aVal);
  898. }
  899. m_Node = null; // Be GC friendly.
  900. }
  901. public override JSONNode this[int aIndex]
  902. {
  903. get
  904. {
  905. return new JSONLazyCreator(this);
  906. }
  907. set
  908. {
  909. var tmp = new JSONArray();
  910. tmp.Add(value);
  911. Set(tmp);
  912. }
  913. }
  914. public override JSONNode this[string aKey]
  915. {
  916. get
  917. {
  918. return new JSONLazyCreator(this, aKey);
  919. }
  920. set
  921. {
  922. var tmp = new JSONClass();
  923. tmp.Add(aKey, value);
  924. Set(tmp);
  925. }
  926. }
  927. public override void Add (JSONNode aItem)
  928. {
  929. var tmp = new JSONArray();
  930. tmp.Add(aItem);
  931. Set(tmp);
  932. }
  933. public override void Add (string aKey, JSONNode aItem)
  934. {
  935. var tmp = new JSONClass();
  936. tmp.Add(aKey, aItem);
  937. Set(tmp);
  938. }
  939. public static bool operator ==(JSONLazyCreator a, object b)
  940. {
  941. if (b == null)
  942. return true;
  943. return ReferenceEquals(a,b);
  944. }
  945. public static bool operator !=(JSONLazyCreator a, object b)
  946. {
  947. return !(a == b);
  948. }
  949. public override bool Equals (object obj)
  950. {
  951. if (obj == null)
  952. return true;
  953. return ReferenceEquals(this, obj);
  954. }
  955. public override int GetHashCode ()
  956. {
  957. return base.GetHashCode();
  958. }
  959. public override string ToString()
  960. {
  961. return "";
  962. }
  963. public override string ToString(string aPrefix)
  964. {
  965. return "";
  966. }
  967. public override int AsInt
  968. {
  969. get
  970. {
  971. JSONData tmp = new JSONData(0);
  972. Set(tmp);
  973. return 0;
  974. }
  975. set
  976. {
  977. JSONData tmp = new JSONData(value);
  978. Set(tmp);
  979. }
  980. }
  981. public override float AsFloat
  982. {
  983. get
  984. {
  985. JSONData tmp = new JSONData(0.0f);
  986. Set(tmp);
  987. return 0.0f;
  988. }
  989. set
  990. {
  991. JSONData tmp = new JSONData(value);
  992. Set(tmp);
  993. }
  994. }
  995. public override double AsDouble
  996. {
  997. get
  998. {
  999. JSONData tmp = new JSONData(0.0);
  1000. Set(tmp);
  1001. return 0.0;
  1002. }
  1003. set
  1004. {
  1005. JSONData tmp = new JSONData(value);
  1006. Set(tmp);
  1007. }
  1008. }
  1009. public override bool AsBool
  1010. {
  1011. get
  1012. {
  1013. JSONData tmp = new JSONData(false);
  1014. Set(tmp);
  1015. return false;
  1016. }
  1017. set
  1018. {
  1019. JSONData tmp = new JSONData(value);
  1020. Set(tmp);
  1021. }
  1022. }
  1023. public override JSONArray AsArray
  1024. {
  1025. get
  1026. {
  1027. JSONArray tmp = new JSONArray();
  1028. Set(tmp);
  1029. return tmp;
  1030. }
  1031. }
  1032. public override JSONClass AsObject
  1033. {
  1034. get
  1035. {
  1036. JSONClass tmp = new JSONClass();
  1037. Set(tmp);
  1038. return tmp;
  1039. }
  1040. }
  1041. } // End of JSONLazyCreator
  1042. public static class JSON
  1043. {
  1044. public static JSONNode Parse(string aJSON)
  1045. {
  1046. return JSONNode.Parse(aJSON);
  1047. }
  1048. }
  1049. }