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