XJson.cs 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. #region Header
  2. /**
  3. * JsonMapper.cs
  4. * JSON to .Net object and object to JSON conversions.
  5. *
  6. * The authors disclaim copyright to this source code. For more details, see
  7. * the COPYING file included with this distribution.
  8. **/
  9. #endregion
  10. using System;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using System.Globalization;
  14. using System.IO;
  15. using System.Reflection;
  16. using XGame.LitJson;
  17. namespace XGame.Framework.Json
  18. {
  19. internal struct PropertyMetadata
  20. {
  21. public MemberInfo Info;
  22. public bool IsField;
  23. public Type Type;
  24. }
  25. internal struct ArrayMetadata
  26. {
  27. private Type element_type;
  28. private bool is_array;
  29. private bool is_list;
  30. private bool is_k_list;
  31. private bool is_k_queue;
  32. private bool is_k_stack;
  33. public Type ElementType
  34. {
  35. get
  36. {
  37. if (element_type == null)
  38. return typeof(JsonData);
  39. return element_type;
  40. }
  41. set { element_type = value; }
  42. }
  43. public bool IsArray
  44. {
  45. get { return is_array; }
  46. set { is_array = value; }
  47. }
  48. public bool IsList
  49. {
  50. get { return is_list; }
  51. set { is_list = value; }
  52. }
  53. public bool IsKList
  54. {
  55. get { return is_k_list; }
  56. set { is_k_list = value; }
  57. }
  58. public bool IsKQueue
  59. {
  60. get { return is_k_queue; }
  61. set { is_k_queue = value; }
  62. }
  63. public bool IsKStack
  64. {
  65. get { return is_k_stack; }
  66. set { is_k_stack = value; }
  67. }
  68. }
  69. internal struct ObjectMetadata
  70. {
  71. private Type element_type;
  72. private bool is_dictionary;
  73. private IDictionary<string, PropertyMetadata> properties;
  74. public Type ElementType
  75. {
  76. get
  77. {
  78. if (element_type == null)
  79. return typeof(JsonData);
  80. return element_type;
  81. }
  82. set { element_type = value; }
  83. }
  84. public bool IsDictionary
  85. {
  86. get { return is_dictionary; }
  87. set { is_dictionary = value; }
  88. }
  89. public IDictionary<string, PropertyMetadata> Properties
  90. {
  91. get { return properties; }
  92. set { properties = value; }
  93. }
  94. }
  95. internal delegate void ExporterFunc(object obj, JsonWriter writer);
  96. public delegate void ExporterFunc<T>(T obj, JsonWriter writer);
  97. internal delegate object ImporterFunc(object input);
  98. public delegate TValue ImporterFunc<TJson, TValue>(TJson input);
  99. public delegate IJsonWrapper WrapperFactory();
  100. public class XJson
  101. {
  102. const BindingFlags FLAGS = BindingFlags.Public | BindingFlags.Instance;
  103. #region Fields
  104. private static int max_nesting_depth;
  105. private static IFormatProvider datetime_format;
  106. private static IDictionary<Type, ExporterFunc> base_exporters_table;
  107. private static IDictionary<Type, ExporterFunc> custom_exporters_table;
  108. private static IDictionary<Type,
  109. IDictionary<Type, ImporterFunc>> base_importers_table;
  110. private static IDictionary<Type,
  111. IDictionary<Type, ImporterFunc>> custom_importers_table;
  112. private static IDictionary<Type, ArrayMetadata> array_metadata;
  113. private static readonly object array_metadata_lock = new Object();
  114. private static IDictionary<Type,
  115. IDictionary<Type, MethodInfo>> conv_ops;
  116. private static readonly object conv_ops_lock = new Object();
  117. private static IDictionary<Type, ObjectMetadata> object_metadata;
  118. private static readonly object object_metadata_lock = new Object();
  119. private static IDictionary<Type,
  120. IList<PropertyMetadata>> type_properties;
  121. private static readonly object type_properties_lock = new Object();
  122. private static JsonWriter static_writer;
  123. private static readonly object static_writer_lock = new Object();
  124. #endregion
  125. #region Constructors
  126. static XJson()
  127. {
  128. max_nesting_depth = 100;
  129. array_metadata = new Dictionary<Type, ArrayMetadata>();
  130. conv_ops = new Dictionary<Type, IDictionary<Type, MethodInfo>>();
  131. object_metadata = new Dictionary<Type, ObjectMetadata>();
  132. type_properties = new Dictionary<Type,
  133. IList<PropertyMetadata>>();
  134. static_writer = new JsonWriter();
  135. datetime_format = DateTimeFormatInfo.InvariantInfo;
  136. base_exporters_table = new Dictionary<Type, ExporterFunc>();
  137. custom_exporters_table = new Dictionary<Type, ExporterFunc>();
  138. base_importers_table = new Dictionary<Type,
  139. IDictionary<Type, ImporterFunc>>();
  140. custom_importers_table = new Dictionary<Type,
  141. IDictionary<Type, ImporterFunc>>();
  142. RegisterBaseExporters();
  143. RegisterBaseImporters();
  144. }
  145. #endregion
  146. internal static void Dispose()
  147. {
  148. object_metadata.Clear();
  149. array_metadata.Clear();
  150. type_properties.Clear();
  151. foreach (var op in conv_ops) op.Value?.Clear();
  152. conv_ops.Clear();
  153. }
  154. #region Private Methods
  155. private static void AddArrayMetadata(Type type)
  156. {
  157. if (array_metadata.ContainsKey(type))
  158. return;
  159. ArrayMetadata data = new ArrayMetadata();
  160. data.IsArray = type.IsArray;
  161. if (type.GetInterface("System.Collections.IList") != null)
  162. data.IsList = true;
  163. if (type.GenericTypeArguments.Length == 1)
  164. {
  165. data.ElementType = type.GenericTypeArguments[0];
  166. }
  167. lock (array_metadata_lock)
  168. {
  169. try
  170. {
  171. array_metadata.Add(type, data);
  172. }
  173. catch (ArgumentException)
  174. {
  175. return;
  176. }
  177. }
  178. }
  179. private static void AddObjectMetadata(Type type)
  180. {
  181. if (object_metadata.ContainsKey(type))
  182. return;
  183. ObjectMetadata data = new ObjectMetadata();
  184. if (type.GetInterface("System.Collections.IDictionary") != null)
  185. data.IsDictionary = true;
  186. data.Properties = new Dictionary<string, PropertyMetadata>();
  187. foreach (PropertyInfo p_info in type.GetProperties(FLAGS))
  188. {
  189. if (p_info.Name == "Item")
  190. {
  191. ParameterInfo[] parameters = p_info.GetIndexParameters();
  192. if (parameters.Length != 1)
  193. continue;
  194. if (parameters[0].ParameterType == typeof(string))
  195. {
  196. data.ElementType = p_info.PropertyType;
  197. }
  198. continue;
  199. }
  200. PropertyMetadata p_data = new PropertyMetadata();
  201. p_data.Info = p_info;
  202. p_data.Type = p_info.PropertyType;
  203. data.Properties.Add(p_info.Name, p_data);
  204. }
  205. foreach (FieldInfo f_info in type.GetFields(FLAGS))
  206. {
  207. PropertyMetadata p_data = new PropertyMetadata();
  208. p_data.Info = f_info;
  209. p_data.IsField = true;
  210. p_data.Type = f_info.FieldType;
  211. data.Properties.Add(f_info.Name, p_data);
  212. }
  213. lock (object_metadata_lock)
  214. {
  215. try
  216. {
  217. object_metadata.Add(type, data);
  218. }
  219. catch (ArgumentException)
  220. {
  221. return;
  222. }
  223. }
  224. }
  225. private static void AddTypeProperties(Type type)
  226. {
  227. if (type_properties.ContainsKey(type))
  228. return;
  229. IList<PropertyMetadata> props = new List<PropertyMetadata>();
  230. foreach (PropertyInfo p_info in type.GetProperties(FLAGS))
  231. {
  232. if (p_info.Name == "Item")
  233. continue;
  234. PropertyMetadata p_data = new PropertyMetadata();
  235. p_data.Info = p_info;
  236. p_data.IsField = false;
  237. props.Add(p_data);
  238. }
  239. foreach (FieldInfo f_info in type.GetFields(FLAGS))
  240. {
  241. PropertyMetadata p_data = new PropertyMetadata();
  242. p_data.Info = f_info;
  243. p_data.IsField = true;
  244. props.Add(p_data);
  245. }
  246. lock (type_properties_lock)
  247. {
  248. try
  249. {
  250. type_properties.Add(type, props);
  251. }
  252. catch (ArgumentException)
  253. {
  254. return;
  255. }
  256. }
  257. }
  258. private static MethodInfo GetConvOp(Type t1, Type t2)
  259. {
  260. lock (conv_ops_lock)
  261. {
  262. if (!conv_ops.ContainsKey(t1))
  263. conv_ops.Add(t1, new Dictionary<Type, MethodInfo>());
  264. }
  265. if (conv_ops[t1].ContainsKey(t2))
  266. return conv_ops[t1][t2];
  267. MethodInfo op = t1.GetMethod(
  268. "op_Implicit", new Type[] { t2 });
  269. lock (conv_ops_lock)
  270. {
  271. try
  272. {
  273. conv_ops[t1].Add(t2, op);
  274. }
  275. catch (ArgumentException)
  276. {
  277. return conv_ops[t1][t2];
  278. }
  279. }
  280. return op;
  281. }
  282. private static object ReadValue(Type inst_type, JsonReader reader)
  283. {
  284. reader.Read();
  285. if (reader.Token == JsonToken.ArrayEnd)
  286. return null;
  287. Type underlying_type = Nullable.GetUnderlyingType(inst_type);
  288. Type value_type = inst_type;
  289. if (reader.Token == JsonToken.Null)
  290. {
  291. if (inst_type.IsClass || underlying_type != null)
  292. {
  293. return null;
  294. }
  295. throw new JsonException(String.Format(
  296. "Can't assign null to an instance of type {0}",
  297. inst_type));
  298. }
  299. if (reader.Token == JsonToken.Double ||
  300. reader.Token == JsonToken.Int ||
  301. reader.Token == JsonToken.Long ||
  302. reader.Token == JsonToken.String ||
  303. reader.Token == JsonToken.Boolean)
  304. {
  305. Type json_type = reader.Value.GetType();
  306. var vt = value_type;
  307. if (vt.IsAssignableFrom(json_type))
  308. return reader.Value;
  309. // If there's a custom importer that fits, use it
  310. if (custom_importers_table.ContainsKey(json_type) &&
  311. custom_importers_table[json_type].ContainsKey(
  312. vt))
  313. {
  314. ImporterFunc importer =
  315. custom_importers_table[json_type][vt];
  316. return importer(reader.Value);
  317. }
  318. // Maybe there's a base importer that works
  319. if (base_importers_table.ContainsKey(json_type) &&
  320. base_importers_table[json_type].ContainsKey(
  321. vt))
  322. {
  323. ImporterFunc importer =
  324. base_importers_table[json_type][vt];
  325. return importer(reader.Value);
  326. }
  327. // Maybe it's an enum
  328. if (vt.IsEnum)
  329. return Enum.ToObject(vt, reader.Value);
  330. // Try using an implicit conversion operator
  331. MethodInfo conv_op = GetConvOp(vt, json_type);
  332. if (conv_op != null)
  333. return conv_op.Invoke(null,
  334. new object[] { reader.Value });
  335. // No luck
  336. throw new JsonException(String.Format(
  337. "Can't assign value '{0}' (type {1}) to type {2}",
  338. reader.Value, json_type, inst_type));
  339. }
  340. object instance = null;
  341. if (reader.Token == JsonToken.ArrayStart)
  342. {
  343. AddArrayMetadata(inst_type);
  344. ArrayMetadata t_data = array_metadata[inst_type];
  345. if (!t_data.IsArray && !t_data.IsList && !t_data.IsKList && t_data.IsKQueue && t_data.IsKStack)
  346. throw new JsonException(String.Format(
  347. "Type {0} can't act as an array",
  348. inst_type));
  349. bool isKCollection = t_data.IsKList || t_data.IsKQueue || t_data.IsKStack;
  350. object kCollection = null;
  351. IList list = null;
  352. Type elem_type;
  353. if (!t_data.IsArray)
  354. {
  355. if (isKCollection)
  356. {
  357. kCollection = Activator.CreateInstance(inst_type);
  358. }
  359. else
  360. {
  361. list = (IList)Activator.CreateInstance(inst_type);
  362. }
  363. elem_type = t_data.ElementType;
  364. }
  365. else
  366. {
  367. list = new ArrayList();
  368. elem_type = inst_type.GetElementType();
  369. }
  370. if (isKCollection)
  371. {
  372. {
  373. MethodInfo AddMethod = null;
  374. if (t_data.IsKQueue)
  375. AddMethod = kCollection.GetType().GetMethod("Enqueue", BindingFlags.Public | BindingFlags.Instance);
  376. else if (t_data.IsKStack)
  377. AddMethod = kCollection.GetType().GetMethod("Push", BindingFlags.Public | BindingFlags.Instance);
  378. object[] param = new object[1];
  379. var count = 0;
  380. while (true)
  381. {
  382. object item = ReadValue(elem_type, reader);
  383. if (item == null && reader.Token == JsonToken.ArrayEnd)
  384. break;
  385. param[0] = item;
  386. AddMethod.Invoke(kCollection, param);
  387. count++;
  388. }
  389. if (t_data.IsKStack && count > 0)
  390. {
  391. MethodInfo popMethod = kCollection.GetType().GetMethod("Pop", BindingFlags.Public | BindingFlags.Instance);
  392. var tempStack = Activator.CreateInstance(inst_type);
  393. object popItem;
  394. while (count > 0)
  395. {
  396. popItem = popMethod.Invoke(kCollection, null);
  397. param[0] = popItem;
  398. AddMethod.Invoke(tempStack, param);
  399. count--;
  400. }
  401. kCollection = tempStack;
  402. }
  403. }
  404. }
  405. else
  406. {
  407. while (true)
  408. {
  409. object item = ReadValue(elem_type, reader);
  410. if (item == null && reader.Token == JsonToken.ArrayEnd)
  411. break;
  412. list.Add(item);
  413. }
  414. }
  415. if (t_data.IsArray)
  416. {
  417. int n = list.Count;
  418. var rt = elem_type;
  419. instance = Array.CreateInstance(rt, n);
  420. for (int i = 0; i < n; i++)
  421. ((Array)instance).SetValue(list[i], i);
  422. }
  423. else
  424. {
  425. if (isKCollection)
  426. instance = kCollection;
  427. else
  428. instance = list;
  429. }
  430. }
  431. else if (reader.Token == JsonToken.ObjectStart)
  432. {
  433. AddObjectMetadata(value_type);
  434. ObjectMetadata t_data = object_metadata[value_type];
  435. instance = Activator.CreateInstance(value_type);
  436. while (true)
  437. {
  438. reader.Read();
  439. if (reader.Token == JsonToken.ObjectEnd)
  440. break;
  441. string property = (string)reader.Value;
  442. if (t_data.Properties.ContainsKey(property))
  443. {
  444. PropertyMetadata prop_data =
  445. t_data.Properties[property];
  446. if (prop_data.IsField)
  447. {
  448. ((FieldInfo)prop_data.Info).SetValue(
  449. instance, ReadValue(prop_data.Type, reader));
  450. }
  451. else
  452. {
  453. PropertyInfo p_info =
  454. (PropertyInfo)prop_data.Info;
  455. if (p_info.CanWrite)
  456. p_info.SetValue(
  457. instance,
  458. ReadValue(prop_data.Type, reader),
  459. null);
  460. else
  461. ReadValue(prop_data.Type, reader);
  462. }
  463. }
  464. else
  465. {
  466. if (!t_data.IsDictionary)
  467. {
  468. if (!reader.SkipNonMembers)
  469. {
  470. throw new JsonException(String.Format(
  471. "The type {0} doesn't have the " +
  472. "property '{1}'",
  473. inst_type, property));
  474. }
  475. else
  476. {
  477. ReadSkip(reader);
  478. continue;
  479. }
  480. }
  481. ((IDictionary)instance).Add(property, ReadValue(t_data.ElementType, reader));
  482. }
  483. }
  484. }
  485. return instance;
  486. }
  487. private static IJsonWrapper ReadValue(WrapperFactory factory,
  488. JsonReader reader)
  489. {
  490. reader.Read();
  491. if (reader.Token == JsonToken.ArrayEnd ||
  492. reader.Token == JsonToken.Null)
  493. return null;
  494. IJsonWrapper instance = factory();
  495. if (reader.Token == JsonToken.String)
  496. {
  497. instance.SetString((string)reader.Value);
  498. return instance;
  499. }
  500. if (reader.Token == JsonToken.Double)
  501. {
  502. instance.SetDouble((double)reader.Value);
  503. return instance;
  504. }
  505. if (reader.Token == JsonToken.Int)
  506. {
  507. instance.SetInt((int)reader.Value);
  508. return instance;
  509. }
  510. if (reader.Token == JsonToken.Long)
  511. {
  512. instance.SetLong((long)reader.Value);
  513. return instance;
  514. }
  515. if (reader.Token == JsonToken.Boolean)
  516. {
  517. instance.SetBoolean((bool)reader.Value);
  518. return instance;
  519. }
  520. if (reader.Token == JsonToken.ArrayStart)
  521. {
  522. instance.SetJsonType(JsonType.Array);
  523. while (true)
  524. {
  525. IJsonWrapper item = ReadValue(factory, reader);
  526. if (item == null && reader.Token == JsonToken.ArrayEnd)
  527. break;
  528. ((IList)instance).Add(item);
  529. }
  530. }
  531. else if (reader.Token == JsonToken.ObjectStart)
  532. {
  533. instance.SetJsonType(JsonType.Object);
  534. while (true)
  535. {
  536. reader.Read();
  537. if (reader.Token == JsonToken.ObjectEnd)
  538. break;
  539. string property = (string)reader.Value;
  540. ((IDictionary)instance)[property] = ReadValue(
  541. factory, reader);
  542. }
  543. }
  544. return instance;
  545. }
  546. private static void ReadSkip(JsonReader reader)
  547. {
  548. ToWrapper(
  549. delegate { return new JsonMockWrapper(); }, reader);
  550. }
  551. private static void RegisterBaseExporters()
  552. {
  553. base_exporters_table[typeof(byte)] =
  554. delegate (object obj, JsonWriter writer)
  555. {
  556. writer.Write(Convert.ToInt32((byte)obj));
  557. };
  558. base_exporters_table[typeof(char)] =
  559. delegate (object obj, JsonWriter writer)
  560. {
  561. writer.Write(Convert.ToString((char)obj));
  562. };
  563. base_exporters_table[typeof(DateTime)] =
  564. delegate (object obj, JsonWriter writer)
  565. {
  566. writer.Write(Convert.ToString((DateTime)obj,
  567. datetime_format));
  568. };
  569. base_exporters_table[typeof(decimal)] =
  570. delegate (object obj, JsonWriter writer)
  571. {
  572. writer.Write((decimal)obj);
  573. };
  574. base_exporters_table[typeof(sbyte)] =
  575. delegate (object obj, JsonWriter writer)
  576. {
  577. writer.Write(Convert.ToInt32((sbyte)obj));
  578. };
  579. base_exporters_table[typeof(short)] =
  580. delegate (object obj, JsonWriter writer)
  581. {
  582. writer.Write(Convert.ToInt32((short)obj));
  583. };
  584. base_exporters_table[typeof(ushort)] =
  585. delegate (object obj, JsonWriter writer)
  586. {
  587. writer.Write(Convert.ToInt32((ushort)obj));
  588. };
  589. base_exporters_table[typeof(uint)] =
  590. delegate (object obj, JsonWriter writer)
  591. {
  592. writer.Write(Convert.ToUInt64((uint)obj));
  593. };
  594. base_exporters_table[typeof(ulong)] =
  595. delegate (object obj, JsonWriter writer)
  596. {
  597. writer.Write((ulong)obj);
  598. };
  599. base_exporters_table[typeof(UnityEngine.Vector2)] =
  600. delegate (object obj, JsonWriter writer)
  601. {
  602. var v = (UnityEngine.Vector2)obj;
  603. writer.WriteObjectStart();
  604. writer.WritePropertyName("x");
  605. writer.Write(v.x);
  606. writer.WritePropertyName("y");
  607. writer.Write(v.y);
  608. writer.WriteObjectEnd();
  609. };
  610. base_exporters_table[typeof(UnityEngine.Vector3)] =
  611. delegate (object obj, JsonWriter writer)
  612. {
  613. var v = (UnityEngine.Vector3)obj;
  614. writer.WriteObjectStart();
  615. writer.WritePropertyName("x");
  616. writer.Write(v.x);
  617. writer.WritePropertyName("y");
  618. writer.Write(v.y);
  619. writer.WritePropertyName("z");
  620. writer.Write(v.z);
  621. writer.WriteObjectEnd();
  622. };
  623. base_exporters_table[typeof(UnityEngine.Vector4)] =
  624. delegate (object obj, JsonWriter writer)
  625. {
  626. var v = (UnityEngine.Vector4)obj;
  627. writer.WriteObjectStart();
  628. writer.WritePropertyName("x");
  629. writer.Write(v.x);
  630. writer.WritePropertyName("y");
  631. writer.Write(v.y);
  632. writer.WritePropertyName("z");
  633. writer.Write(v.z);
  634. writer.WritePropertyName("w");
  635. writer.Write(v.z);
  636. writer.WriteObjectEnd();
  637. };
  638. base_exporters_table[typeof(UnityEngine.Quaternion)] =
  639. delegate (object obj, JsonWriter writer)
  640. {
  641. var v = (UnityEngine.Quaternion)obj;
  642. writer.WriteObjectStart();
  643. writer.WritePropertyName("x");
  644. writer.Write(v.x);
  645. writer.WritePropertyName("y");
  646. writer.Write(v.y);
  647. writer.WritePropertyName("z");
  648. writer.Write(v.z);
  649. writer.WritePropertyName("w");
  650. writer.Write(v.z);
  651. writer.WriteObjectEnd();
  652. };
  653. base_exporters_table[typeof(UnityEngine.Color)] =
  654. delegate (object obj, JsonWriter writer)
  655. {
  656. var v = (UnityEngine.Color)obj;
  657. writer.WriteObjectStart();
  658. writer.WritePropertyName("r");
  659. writer.Write(v.r);
  660. writer.WritePropertyName("g");
  661. writer.Write(v.g);
  662. writer.WritePropertyName("b");
  663. writer.Write(v.b);
  664. writer.WritePropertyName("a");
  665. writer.Write(v.a);
  666. writer.WriteObjectEnd();
  667. };
  668. base_exporters_table[typeof(UnityEngine.Color32)] =
  669. delegate (object obj, JsonWriter writer)
  670. {
  671. var v = (UnityEngine.Color32)obj;
  672. writer.WriteObjectStart();
  673. writer.WritePropertyName("r");
  674. writer.Write(v.r);
  675. writer.WritePropertyName("g");
  676. writer.Write(v.g);
  677. writer.WritePropertyName("b");
  678. writer.Write(v.b);
  679. writer.WritePropertyName("a");
  680. writer.Write(v.a);
  681. writer.WriteObjectEnd();
  682. };
  683. }
  684. private static void RegisterBaseImporters()
  685. {
  686. ImporterFunc importer;
  687. importer = delegate (object input)
  688. {
  689. return Convert.ToByte((int)input);
  690. };
  691. RegisterImporter(base_importers_table, typeof(int),
  692. typeof(byte), importer);
  693. importer = delegate (object input)
  694. {
  695. return Convert.ToUInt64((int)input);
  696. };
  697. RegisterImporter(base_importers_table, typeof(int),
  698. typeof(ulong), importer);
  699. importer = delegate (object input)
  700. {
  701. return Convert.ToSByte((int)input);
  702. };
  703. RegisterImporter(base_importers_table, typeof(int),
  704. typeof(sbyte), importer);
  705. importer = delegate (object input)
  706. {
  707. return Convert.ToInt16((int)input);
  708. };
  709. RegisterImporter(base_importers_table, typeof(int),
  710. typeof(short), importer);
  711. importer = delegate (object input)
  712. {
  713. return Convert.ToInt64((int)input);
  714. };
  715. RegisterImporter(base_importers_table, typeof(int),
  716. typeof(long), importer);
  717. importer = delegate (object input)
  718. {
  719. return Convert.ToUInt16((int)input);
  720. };
  721. RegisterImporter(base_importers_table, typeof(int),
  722. typeof(ushort), importer);
  723. importer = delegate (object input)
  724. {
  725. return Convert.ToUInt32((int)input);
  726. };
  727. RegisterImporter(base_importers_table, typeof(int),
  728. typeof(uint), importer);
  729. importer = delegate (object input)
  730. {
  731. return Convert.ToSingle((int)input);
  732. };
  733. RegisterImporter(base_importers_table, typeof(int),
  734. typeof(float), importer);
  735. importer = delegate (object input)
  736. {
  737. return Convert.ToDouble((int)input);
  738. };
  739. RegisterImporter(base_importers_table, typeof(int),
  740. typeof(double), importer);
  741. importer = delegate (object input)
  742. {
  743. return Convert.ToDecimal((double)input);
  744. };
  745. RegisterImporter(base_importers_table, typeof(double),
  746. typeof(decimal), importer);
  747. importer = delegate (object input)
  748. {
  749. return Convert.ToSingle((double)input);
  750. };
  751. RegisterImporter(base_importers_table, typeof(double),
  752. typeof(float), importer);
  753. importer = delegate (object input)
  754. {
  755. return Convert.ToUInt32((long)input);
  756. };
  757. RegisterImporter(base_importers_table, typeof(long),
  758. typeof(uint), importer);
  759. importer = delegate (object input)
  760. {
  761. return Convert.ToChar((string)input);
  762. };
  763. RegisterImporter(base_importers_table, typeof(string),
  764. typeof(char), importer);
  765. importer = delegate (object input)
  766. {
  767. return Convert.ToInt32((string)input);
  768. };
  769. RegisterImporter(base_importers_table, typeof(string),
  770. typeof(int), importer);
  771. importer = delegate (object input)
  772. {
  773. return Convert.ToDateTime((string)input, datetime_format);
  774. };
  775. RegisterImporter(base_importers_table, typeof(string),
  776. typeof(DateTime), importer);
  777. importer = delegate (object input)
  778. {
  779. return DateTimeOffset.Parse((string)input, datetime_format);
  780. };
  781. RegisterImporter(base_importers_table, typeof(string),
  782. typeof(DateTimeOffset), importer);
  783. }
  784. private static void RegisterImporter(
  785. IDictionary<Type, IDictionary<Type, ImporterFunc>> table,
  786. Type json_type, Type value_type, ImporterFunc importer)
  787. {
  788. if (!table.ContainsKey(json_type))
  789. table.Add(json_type, new Dictionary<Type, ImporterFunc>());
  790. table[json_type][value_type] = importer;
  791. }
  792. private static void WriteValue(object obj, JsonWriter writer,
  793. bool writer_is_private,
  794. int depth)
  795. {
  796. if (depth > max_nesting_depth)
  797. throw new JsonException(
  798. String.Format("Max allowed object depth reached while " +
  799. "trying to export from type {0}",
  800. obj.GetType()));
  801. if (obj == null)
  802. {
  803. writer.Write(null);
  804. return;
  805. }
  806. if (obj is IJsonWrapper jsonwrapper)
  807. {
  808. if (writer_is_private)
  809. writer.WriteJsonWrapper(jsonwrapper);
  810. else
  811. ((IJsonWrapper)obj).ToJson(writer);
  812. return;
  813. }
  814. if (obj is String)
  815. {
  816. writer.Write((string)obj);
  817. return;
  818. }
  819. if (obj is Single)
  820. {
  821. writer.Write((float)obj);
  822. return;
  823. }
  824. if (obj is Double)
  825. {
  826. writer.Write((double)obj);
  827. return;
  828. }
  829. if (obj is Int32)
  830. {
  831. writer.Write((int)obj);
  832. return;
  833. }
  834. if (obj is Boolean)
  835. {
  836. writer.Write((bool)obj);
  837. return;
  838. }
  839. if (obj is Int64)
  840. {
  841. writer.Write((long)obj);
  842. return;
  843. }
  844. if (obj is Array)
  845. {
  846. writer.WriteArrayStart();
  847. foreach (object elem in (Array)obj)
  848. WriteValue(elem, writer, writer_is_private, depth + 1);
  849. writer.WriteArrayEnd();
  850. return;
  851. }
  852. if (obj is IList)
  853. {
  854. writer.WriteArrayStart();
  855. foreach (object elem in (IList)obj)
  856. WriteValue(elem, writer, writer_is_private, depth + 1);
  857. writer.WriteArrayEnd();
  858. return;
  859. }
  860. if (obj is IDictionary)
  861. {
  862. writer.WriteObjectStart();
  863. foreach (DictionaryEntry entry in (IDictionary)obj)
  864. {
  865. writer.WritePropertyName(entry.Key.ToString());
  866. WriteValue(entry.Value, writer, writer_is_private,
  867. depth + 1);
  868. }
  869. writer.WriteObjectEnd();
  870. return;
  871. }
  872. Type obj_type = obj.GetType();
  873. // See if there's a custom exporter for the object
  874. if (custom_exporters_table.ContainsKey(obj_type))
  875. {
  876. ExporterFunc exporter = custom_exporters_table[obj_type];
  877. exporter(obj, writer);
  878. return;
  879. }
  880. // If not, maybe there's a base exporter
  881. if (base_exporters_table.ContainsKey(obj_type))
  882. {
  883. ExporterFunc exporter = base_exporters_table[obj_type];
  884. exporter(obj, writer);
  885. return;
  886. }
  887. // Last option, let's see if it's an enum
  888. if (obj is Enum)
  889. {
  890. Type e_type = Enum.GetUnderlyingType(obj_type);
  891. if (e_type == typeof(long)
  892. || e_type == typeof(uint)
  893. || e_type == typeof(ulong))
  894. writer.Write((ulong)obj);
  895. else
  896. writer.Write((int)obj);
  897. return;
  898. }
  899. // Okay, so it looks like the input should be exported as an
  900. // object
  901. AddTypeProperties(obj_type);
  902. IList<PropertyMetadata> props = type_properties[obj_type];
  903. writer.WriteObjectStart();
  904. foreach (PropertyMetadata p_data in props)
  905. {
  906. if (p_data.IsField)
  907. {
  908. writer.WritePropertyName(p_data.Info.Name);
  909. WriteValue(((FieldInfo)p_data.Info).GetValue(obj),
  910. writer, writer_is_private, depth + 1);
  911. }
  912. else
  913. {
  914. PropertyInfo p_info = (PropertyInfo)p_data.Info;
  915. if (p_info.CanRead)
  916. {
  917. writer.WritePropertyName(p_data.Info.Name);
  918. WriteValue(p_info.GetValue(obj, null),
  919. writer, writer_is_private, depth + 1);
  920. }
  921. }
  922. }
  923. writer.WriteObjectEnd();
  924. }
  925. #endregion
  926. public static string ToJson(object obj)
  927. {
  928. lock (static_writer_lock)
  929. {
  930. static_writer.Reset();
  931. WriteValue(obj, static_writer, true, 0);
  932. return static_writer.ToString();
  933. }
  934. }
  935. internal static void ToJson(object obj, JsonWriter writer)
  936. {
  937. WriteValue(obj, writer, false, 0);
  938. }
  939. internal static JsonData ToObject(JsonReader reader)
  940. {
  941. return (JsonData)ToWrapper(
  942. delegate { return new JsonData(); }, reader);
  943. }
  944. internal static JsonData ToObject(TextReader reader)
  945. {
  946. JsonReader json_reader = new JsonReader(reader);
  947. return (JsonData)ToWrapper(
  948. delegate { return new JsonData(); }, json_reader);
  949. }
  950. public static JsonData ToObject(string json)
  951. {
  952. return (JsonData)ToWrapper(
  953. delegate { return new JsonData(); }, json);
  954. }
  955. internal static T ToObject<T>(JsonReader reader)
  956. {
  957. return (T)ReadValue(typeof(T), reader);
  958. }
  959. internal static T ToObject<T>(TextReader reader)
  960. {
  961. JsonReader json_reader = new JsonReader(reader);
  962. return (T)ReadValue(typeof(T), json_reader);
  963. }
  964. public static T ToObject<T>(string json)
  965. {
  966. JsonReader reader = new JsonReader(json);
  967. return (T)ReadValue(typeof(T), reader);
  968. }
  969. public static object ToObject(string json, Type type)
  970. {
  971. JsonReader reader = new JsonReader(json);
  972. return ReadValue(type, reader);
  973. }
  974. internal static IJsonWrapper ToWrapper(WrapperFactory factory,
  975. JsonReader reader)
  976. {
  977. return ReadValue(factory, reader);
  978. }
  979. internal static IJsonWrapper ToWrapper(WrapperFactory factory,
  980. string json)
  981. {
  982. JsonReader reader = new JsonReader(json);
  983. return ReadValue(factory, reader);
  984. }
  985. internal static void RegisterExporter<T>(ExporterFunc<T> exporter)
  986. {
  987. ExporterFunc exporter_wrapper =
  988. delegate (object obj, JsonWriter writer)
  989. {
  990. exporter((T)obj, writer);
  991. };
  992. custom_exporters_table[typeof(T)] = exporter_wrapper;
  993. }
  994. internal static void RegisterImporter<TJson, TValue>(
  995. ImporterFunc<TJson, TValue> importer)
  996. {
  997. ImporterFunc importer_wrapper =
  998. delegate (object input)
  999. {
  1000. return importer((TJson)input);
  1001. };
  1002. RegisterImporter(custom_importers_table, typeof(TJson),
  1003. typeof(TValue), importer_wrapper);
  1004. }
  1005. internal static void UnregisterExporters()
  1006. {
  1007. custom_exporters_table.Clear();
  1008. }
  1009. internal static void UnregisterImporters()
  1010. {
  1011. custom_importers_table.Clear();
  1012. }
  1013. }
  1014. }