SimpleJSON.cs 33 KB

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