JSON.cs 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. #if !SILVERLIGHT
  5. using System.Data;
  6. #endif
  7. using System.Globalization;
  8. using System.IO;
  9. using System.Reflection;
  10. using System.Reflection.Emit;
  11. using System.Collections.Specialized;
  12. namespace FastJSON
  13. {
  14. public delegate string Serialize(object data);
  15. public delegate object Deserialize(string data);
  16. public sealed class JSONParameters
  17. {
  18. /// <summary>
  19. /// Use the optimized fast Dataset Schema format (default = True)
  20. /// </summary>
  21. public bool UseOptimizedDatasetSchema = true;
  22. /// <summary>
  23. /// Use the fast GUID format (default = True)
  24. /// </summary>
  25. public bool UseFastGuid = true;
  26. /// <summary>
  27. /// Serialize null values to the output (default = True)
  28. /// </summary>
  29. public bool SerializeNullValues = true;
  30. /// <summary>
  31. /// Use the UTC date format (default = True)
  32. /// </summary>
  33. public bool UseUTCDateTime = true;
  34. /// <summary>
  35. /// Show the readonly properties of types in the output (default = False)
  36. /// </summary>
  37. public bool ShowReadOnlyProperties = false;
  38. /// <summary>
  39. /// Use the $types extension to optimise the output json (default = True)
  40. /// </summary>
  41. public bool UsingGlobalTypes = true;
  42. /// <summary>
  43. /// Ignore case when processing json and deserializing
  44. /// </summary>
  45. [Obsolete("Not needed anymore and will always match")]
  46. public bool IgnoreCaseOnDeserialize = false;
  47. /// <summary>
  48. /// Anonymous types have read only properties
  49. /// </summary>
  50. public bool EnableAnonymousTypes = false;
  51. /// <summary>
  52. /// Enable fastJSON extensions $types, $type, $map (default = True)
  53. /// </summary>
  54. public bool UseExtensions = true;
  55. /// <summary>
  56. /// Use escaped unicode i.e. \uXXXX format for non ASCII characters (default = True)
  57. /// </summary>
  58. public bool UseEscapedUnicode = false;
  59. /// <summary>
  60. /// Output string key dictionaries as "k"/"v" format (default = False)
  61. /// </summary>
  62. public bool KVStyleStringDictionary = false;
  63. /// <summary>
  64. /// Output Enum values instead of names (default = False)
  65. /// </summary>
  66. public bool UseValuesOfEnums = false;
  67. /// <summary>
  68. /// Ignore attributes to check for (default : XmlIgnoreAttribute)
  69. /// </summary>
  70. public List<Type> IgnoreAttributes = new List<Type> { typeof(System.Xml.Serialization.XmlIgnoreAttribute) };
  71. /// <summary>
  72. /// If you have parametric and no default constructor for you classes (default = False)
  73. ///
  74. /// IMPORTANT NOTE : If True then all initial values within the class will be ignored and will be not set
  75. /// </summary>
  76. public bool ParametricConstructorOverride = false;
  77. /// <summary>
  78. /// Serialize DateTime milliseconds i.e. yyyy-MM-dd HH:mm:ss.nnn (default = false)
  79. /// </summary>
  80. public bool DateTimeMilliseconds = false;
  81. /// <summary>
  82. /// Maximum depth for circular references in inline mode (default = 20)
  83. /// </summary>
  84. public byte SerializerMaxDepth = 20;
  85. /// <summary>
  86. /// Inline circular or already seen objects instead of replacement with $i (default = False)
  87. /// </summary>
  88. public bool InlineCircularReferences = false;
  89. /// <summary>
  90. /// Save property/field names as lowercase (default = false)
  91. /// </summary>
  92. public bool SerializeToLowerCaseNames = false;
  93. /// <summary>
  94. /// Serialize property name with underline style
  95. /// </summary>
  96. public bool UseApiNamingStyle = false;
  97. public void FixValues()
  98. {
  99. if (UseExtensions == false) // disable conflicting params
  100. {
  101. UsingGlobalTypes = false;
  102. InlineCircularReferences = true;
  103. }
  104. if (EnableAnonymousTypes)
  105. ShowReadOnlyProperties = true;
  106. }
  107. }
  108. public static class JSON
  109. {
  110. /// <summary>
  111. /// Globally set-able parameters for controlling the serializer
  112. /// </summary>
  113. public static JSONParameters Parameters = new JSONParameters();
  114. /// <summary>
  115. /// Create a formatted json string (beautified) from an object
  116. /// </summary>
  117. /// <param name="obj"></param>
  118. /// <param name="param"></param>
  119. /// <returns></returns>
  120. public static string ToNiceJSON(object obj, JSONParameters param)
  121. {
  122. string s = ToJSON(obj, param);
  123. return Beautify(s);
  124. }
  125. /// <summary>
  126. /// Create a json representation for an object
  127. /// </summary>
  128. /// <param name="obj"></param>
  129. /// <returns></returns>
  130. public static string ToJSON(object obj)
  131. {
  132. return ToJSON(obj, JSON.Parameters);
  133. }
  134. /// <summary>
  135. /// Create a json representation for an object with parameter override on this call
  136. /// </summary>
  137. /// <param name="obj"></param>
  138. /// <param name="param"></param>
  139. /// <returns></returns>
  140. public static string ToJSON(object obj, JSONParameters param)
  141. {
  142. param.FixValues();
  143. Type t = null;
  144. if (obj == null)
  145. return "null";
  146. if (obj.GetType().IsGenericType)
  147. t = Reflection.Instance.GetGenericTypeDefinition(obj.GetType());
  148. if (t == typeof(Dictionary<,>) || t == typeof(List<>))
  149. param.UsingGlobalTypes = false;
  150. // FEATURE : enable extensions when you can deserialize anon types
  151. if (param.EnableAnonymousTypes) { param.UseExtensions = false; param.UsingGlobalTypes = false; }
  152. return new JSONSerializer(param).ConvertToJSON(obj);
  153. }
  154. /// <summary>
  155. /// Parse a json string and generate a Dictionary&lt;string,object&gt; or List&lt;object&gt; structure
  156. /// </summary>
  157. /// <param name="json"></param>
  158. /// <returns></returns>
  159. public static object Parse(string json)
  160. {
  161. return new JsonParser(json).Decode();
  162. }
  163. #if net4
  164. /// <summary>
  165. /// Create a .net4 dynamic object from the json string
  166. /// </summary>
  167. /// <param name="json"></param>
  168. /// <returns></returns>
  169. public static dynamic ToDynamic(string json)
  170. {
  171. return new DynamicJson(json);
  172. }
  173. #endif
  174. /// <summary>
  175. /// Create a typed generic object from the json
  176. /// </summary>
  177. /// <typeparam name="T"></typeparam>
  178. /// <param name="json"></param>
  179. /// <returns></returns>
  180. public static T ToObject<T>(string json)
  181. {
  182. return new deserializer(Parameters).ToObject<T>(json);
  183. }
  184. /// <summary>
  185. /// Create a typed generic object from the json with parameter override on this call
  186. /// </summary>
  187. /// <typeparam name="T"></typeparam>
  188. /// <param name="json"></param>
  189. /// <param name="param"></param>
  190. /// <returns></returns>
  191. public static T ToObject<T>(string json, JSONParameters param)
  192. {
  193. return new deserializer(param).ToObject<T>(json);
  194. }
  195. /// <summary>
  196. /// Create an object from the json
  197. /// </summary>
  198. /// <param name="json"></param>
  199. /// <returns></returns>
  200. public static object ToObject(string json)
  201. {
  202. return new deserializer(Parameters).ToObject(json, null);
  203. }
  204. /// <summary>
  205. /// Create an object from the json with parameter override on this call
  206. /// </summary>
  207. /// <param name="json"></param>
  208. /// <param name="param"></param>
  209. /// <returns></returns>
  210. public static object ToObject(string json, JSONParameters param)
  211. {
  212. return new deserializer(param).ToObject(json, null);
  213. }
  214. /// <summary>
  215. /// Create an object of type from the json
  216. /// </summary>
  217. /// <param name="json"></param>
  218. /// <param name="type"></param>
  219. /// <returns></returns>
  220. public static object ToObject(string json, Type type)
  221. {
  222. return new deserializer(Parameters).ToObject(json, type);
  223. }
  224. /// <summary>
  225. /// Fill a given object with the json represenation
  226. /// </summary>
  227. /// <param name="input"></param>
  228. /// <param name="json"></param>
  229. /// <returns></returns>
  230. public static object FillObject(object input, string json)
  231. {
  232. Dictionary<string, object> ht = new JsonParser(json).Decode() as Dictionary<string, object>;
  233. if (ht == null) return null;
  234. return new deserializer(Parameters).ParseDictionary(ht, null, input.GetType(), input);
  235. }
  236. /// <summary>
  237. /// Deep copy an object i.e. clone to a new object
  238. /// </summary>
  239. /// <param name="obj"></param>
  240. /// <returns></returns>
  241. public static object DeepCopy(object obj)
  242. {
  243. return new deserializer(Parameters).ToObject(ToJSON(obj));
  244. }
  245. /// <summary>
  246. ///
  247. /// </summary>
  248. /// <typeparam name="T"></typeparam>
  249. /// <param name="obj"></param>
  250. /// <returns></returns>
  251. public static T DeepCopy<T>(T obj)
  252. {
  253. return new deserializer(Parameters).ToObject<T>(ToJSON(obj));
  254. }
  255. /// <summary>
  256. /// Create a human readable string from the json
  257. /// </summary>
  258. /// <param name="input"></param>
  259. /// <returns></returns>
  260. public static string Beautify(string input)
  261. {
  262. return Formatter.PrettyPrint(input);
  263. }
  264. /// <summary>
  265. /// Register custom type handlers for your own types not natively handled by fastJSON
  266. /// </summary>
  267. /// <param name="type"></param>
  268. /// <param name="serializer"></param>
  269. /// <param name="deserializer"></param>
  270. public static void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer)
  271. {
  272. Reflection.Instance.RegisterCustomType(type, serializer, deserializer);
  273. }
  274. /// <summary>
  275. /// Clear the internal reflection cache so you can start from new (you will loose performance)
  276. /// </summary>
  277. public static void ClearReflectionCache()
  278. {
  279. Reflection.Instance.ClearReflectionCache();
  280. }
  281. internal static long CreateLong(out long num, string s, int index, int count)
  282. {
  283. num = 0;
  284. bool neg = false;
  285. for (int x = 0; x < count; x++, index++)
  286. {
  287. char cc = s[index];
  288. if (cc == '-')
  289. neg = true;
  290. else if (cc == '+')
  291. neg = false;
  292. else
  293. {
  294. num *= 10;
  295. num += (int)(cc - '0');
  296. }
  297. }
  298. if (neg) num = -num;
  299. return num;
  300. }
  301. }
  302. internal class deserializer
  303. {
  304. public deserializer(JSONParameters param)
  305. {
  306. _params = param;
  307. }
  308. private JSONParameters _params;
  309. private bool _usingglobals = false;
  310. private Dictionary<object, int> _circobj = new Dictionary<object, int>();
  311. private Dictionary<int, object> _cirrev = new Dictionary<int, object>();
  312. public T ToObject<T>(string json)
  313. {
  314. Type t = typeof(T);
  315. var o = ToObject(json, t);
  316. if (t.IsArray)
  317. {
  318. if ((o as ICollection).Count == 0) // edge case for "[]" -> T[]
  319. {
  320. Type tt = t.GetElementType();
  321. object oo = Array.CreateInstance(tt, 0);
  322. return (T)oo;
  323. }
  324. else
  325. return (T)o;
  326. }
  327. else
  328. return (T)o;
  329. }
  330. public object ToObject(string json)
  331. {
  332. return ToObject(json, null);
  333. }
  334. public object ToObject(string json, Type type)
  335. {
  336. //_params = Parameters;
  337. _params.FixValues();
  338. Type t = null;
  339. if (type != null && type.IsGenericType)
  340. t = Reflection.Instance.GetGenericTypeDefinition(type);
  341. if (t == typeof(Dictionary<,>) || t == typeof(List<>))
  342. _params.UsingGlobalTypes = false;
  343. _usingglobals = _params.UsingGlobalTypes;
  344. object o = new JsonParser(json).Decode();
  345. if (o == null)
  346. return null;
  347. #if !SILVERLIGHT
  348. if (type != null && type == typeof(DataSet))
  349. return CreateDataset(o as Dictionary<string, object>, null);
  350. else if (type != null && type == typeof(DataTable))
  351. return CreateDataTable(o as Dictionary<string, object>, null);
  352. #endif
  353. if (o is IDictionary)
  354. {
  355. if (type != null && t == typeof(Dictionary<,>)) // deserialize a dictionary
  356. return RootDictionary(o, type);
  357. else // deserialize an object
  358. return ParseDictionary(o as Dictionary<string, object>, null, type, null);
  359. }
  360. else if (o is List<object>)
  361. {
  362. if (type != null && t == typeof(Dictionary<,>)) // kv format
  363. return RootDictionary(o, type);
  364. else if (type != null && t == typeof(List<>)) // deserialize to generic list
  365. return RootList(o, type);
  366. else if (type == typeof(Hashtable))
  367. return RootHashTable((List<object>)o);
  368. else
  369. return (o as List<object>).ToArray();
  370. }
  371. else if (type != null && o.GetType() != type)
  372. return ChangeType(o, type);
  373. return o;
  374. }
  375. #region [ p r i v a t e m e t h o d s ]
  376. private object RootHashTable(List<object> o)
  377. {
  378. Hashtable h = new Hashtable();
  379. foreach (Dictionary<string, object> values in o)
  380. {
  381. object key = values["k"];
  382. object val = values["v"];
  383. if (key is Dictionary<string, object>)
  384. key = ParseDictionary((Dictionary<string, object>)key, null, typeof(object), null);
  385. if (val is Dictionary<string, object>)
  386. val = ParseDictionary((Dictionary<string, object>)val, null, typeof(object), null);
  387. h.Add(key, val);
  388. }
  389. return h;
  390. }
  391. private object ChangeType(object value, Type conversionType)
  392. {
  393. if (conversionType == typeof(int))
  394. return (int)((long)value);
  395. else if (conversionType == typeof(long))
  396. return (long)value;
  397. else if (conversionType == typeof(string))
  398. return (string)value;
  399. else if (conversionType.IsEnum)
  400. return CreateEnum(conversionType, value);
  401. else if (conversionType == typeof(DateTime))
  402. return CreateDateTime((string)value);
  403. else if (Reflection.Instance.IsTypeRegistered(conversionType))
  404. return Reflection.Instance.CreateCustom((string)value, conversionType);
  405. // 8-30-2014 - James Brooks - Added code for nullable types.
  406. if (IsNullable(conversionType))
  407. {
  408. if (value == null)
  409. {
  410. return value;
  411. }
  412. conversionType = UnderlyingTypeOf(conversionType);
  413. }
  414. // 8-30-2014 - James Brooks - Nullable Guid is a special case so it was moved after the "IsNullable" check.
  415. if (conversionType == typeof(Guid))
  416. return CreateGuid((string)value);
  417. return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture);
  418. }
  419. private bool IsNullable(Type t)
  420. {
  421. if (!t.IsGenericType) return false;
  422. Type g = t.GetGenericTypeDefinition();
  423. return (g.Equals(typeof(Nullable<>)));
  424. }
  425. private Type UnderlyingTypeOf(Type t)
  426. {
  427. return t.GetGenericArguments()[0];
  428. }
  429. private object RootList(object parse, Type type)
  430. {
  431. Type[] gtypes = Reflection.Instance.GetGenericArguments(type);
  432. IList o = (IList)Reflection.Instance.FastCreateInstance(type);
  433. foreach (var k in (IList)parse)
  434. {
  435. _usingglobals = false;
  436. object v = k;
  437. if (k is Dictionary<string, object>)
  438. v = ParseDictionary(k as Dictionary<string, object>, null, gtypes[0], null);
  439. else
  440. v = ChangeType(k, gtypes[0]);
  441. o.Add(v);
  442. }
  443. return o;
  444. }
  445. private object RootDictionary(object parse, Type type)
  446. {
  447. Type[] gtypes = Reflection.Instance.GetGenericArguments(type);
  448. Type t1 = null;
  449. Type t2 = null;
  450. if (gtypes != null)
  451. {
  452. t1 = gtypes[0];
  453. t2 = gtypes[1];
  454. }
  455. if (parse is Dictionary<string, object>)
  456. {
  457. IDictionary o = (IDictionary)Reflection.Instance.FastCreateInstance(type);
  458. foreach (var kv in (Dictionary<string, object>)parse)
  459. {
  460. object v;
  461. object k = ChangeType(kv.Key, t1);
  462. if (kv.Value is Dictionary<string, object>)
  463. v = ParseDictionary(kv.Value as Dictionary<string, object>, null, t2, null);
  464. else if (t2.IsArray)
  465. v = CreateArray((List<object>)kv.Value, t2, t2.GetElementType(), null);
  466. else if (kv.Value is IList)
  467. v = CreateGenericList((List<object>)kv.Value, t2, t1, null);
  468. else
  469. v = ChangeType(kv.Value, t2);
  470. o.Add(k, v);
  471. }
  472. return o;
  473. }
  474. if (parse is List<object>)
  475. return CreateDictionary(parse as List<object>, type, gtypes, null);
  476. return null;
  477. }
  478. internal object ParseDictionary(Dictionary<string, object> d, Dictionary<string, object> globaltypes, Type type, object input)
  479. {
  480. object tn = "";
  481. if (type == typeof(NameValueCollection))
  482. return CreateNV(d);
  483. if (type == typeof(StringDictionary))
  484. return CreateSD(d);
  485. if (d.TryGetValue("$i", out tn))
  486. {
  487. object v = null;
  488. _cirrev.TryGetValue((int)(long)tn, out v);
  489. return v;
  490. }
  491. if (d.TryGetValue("$types", out tn))
  492. {
  493. _usingglobals = true;
  494. globaltypes = new Dictionary<string, object>();
  495. foreach (var kv in (Dictionary<string, object>)tn)
  496. {
  497. globaltypes.Add((string)kv.Value, kv.Key);
  498. }
  499. }
  500. bool found = d.TryGetValue("$type", out tn);
  501. #if !SILVERLIGHT
  502. if (found == false && type == typeof(System.Object))
  503. {
  504. return d; // CreateDataset(d, globaltypes);
  505. }
  506. #endif
  507. if (found)
  508. {
  509. if (_usingglobals)
  510. {
  511. object tname = "";
  512. if (globaltypes != null && globaltypes.TryGetValue((string)tn, out tname))
  513. tn = tname;
  514. }
  515. type = Reflection.Instance.GetTypeFromCache((string)tn);
  516. }
  517. if (type == null)
  518. throw new Exception("Cannot determine type");
  519. string typename = type.FullName;
  520. object o = input;
  521. if (o == null)
  522. {
  523. if (_params.ParametricConstructorOverride)
  524. o = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type);
  525. else
  526. o = Reflection.Instance.FastCreateInstance(type);
  527. }
  528. int circount = 0;
  529. if (_circobj.TryGetValue(o, out circount) == false)
  530. {
  531. circount = _circobj.Count + 1;
  532. _circobj.Add(o, circount);
  533. _cirrev.Add(circount, o);
  534. }
  535. Dictionary<string, myPropInfo> props = Reflection.Instance.Getproperties(type, typename, Reflection.Instance.IsTypeRegistered(type));
  536. foreach (var kv in d)
  537. {
  538. var n = kv.Key;
  539. var v = kv.Value;
  540. string name = n.ToLower();
  541. if (name == "$map")
  542. {
  543. ProcessMap(o, props, (Dictionary<string, object>)d[name]);
  544. continue;
  545. }
  546. myPropInfo pi;
  547. if (props.TryGetValue(name, out pi) == false)
  548. continue;
  549. if (pi.CanWrite)
  550. {
  551. //object v = d[n];
  552. if (v != null)
  553. {
  554. object oset = null;
  555. switch (pi.Type)
  556. {
  557. case myPropInfoType.Int: oset = (int)((long)v); break;
  558. case myPropInfoType.Long: oset = (long)v; break;
  559. case myPropInfoType.String: oset = (string)v; break;
  560. case myPropInfoType.Bool: oset = (bool)v; break;
  561. case myPropInfoType.DateTime: oset = CreateDateTime((string)v); break;
  562. case myPropInfoType.Enum: oset = CreateEnum(pi.pt, v); break;
  563. case myPropInfoType.Guid: oset = CreateGuid((string)v); break;
  564. case myPropInfoType.Array:
  565. if (!pi.IsValueType)
  566. oset = CreateArray((List<object>)v, pi.pt, pi.bt, globaltypes);
  567. // what about 'else'?
  568. break;
  569. case myPropInfoType.ByteArray: oset = Convert.FromBase64String((string)v); break;
  570. #if !SILVERLIGHT
  571. case myPropInfoType.DataSet: oset = CreateDataset((Dictionary<string, object>)v, globaltypes); break;
  572. case myPropInfoType.DataTable: oset = CreateDataTable((Dictionary<string, object>)v, globaltypes); break;
  573. case myPropInfoType.Hashtable: // same case as Dictionary
  574. #endif
  575. case myPropInfoType.Dictionary: oset = CreateDictionary((List<object>)v, pi.pt, pi.GenericTypes, globaltypes); break;
  576. case myPropInfoType.StringKeyDictionary: oset = CreateStringKeyDictionary((Dictionary<string, object>)v, pi.pt, pi.GenericTypes, globaltypes); break;
  577. case myPropInfoType.NameValue: oset = CreateNV((Dictionary<string, object>)v); break;
  578. case myPropInfoType.StringDictionary: oset = CreateSD((Dictionary<string, object>)v); break;
  579. case myPropInfoType.Custom: oset = Reflection.Instance.CreateCustom((string)v, pi.pt); break;
  580. default:
  581. {
  582. if (pi.IsGenericType && pi.IsValueType == false && v is List<object>)
  583. oset = CreateGenericList((List<object>)v, pi.pt, pi.bt, globaltypes);
  584. else if ((pi.IsClass || pi.IsStruct) && v is Dictionary<string, object>)
  585. oset = ParseDictionary((Dictionary<string, object>)v, globaltypes, pi.pt, pi.getter(o));
  586. else if (v is List<object>)
  587. oset = CreateArray((List<object>)v, pi.pt, typeof(object), globaltypes);
  588. else if (pi.IsValueType)
  589. oset = ChangeType(v, pi.changeType);
  590. else
  591. oset = v;
  592. }
  593. break;
  594. }
  595. o = pi.setter(o, oset);
  596. }
  597. }
  598. }
  599. return o;
  600. }
  601. private StringDictionary CreateSD(Dictionary<string, object> d)
  602. {
  603. StringDictionary nv = new StringDictionary();
  604. foreach (var o in d)
  605. nv.Add(o.Key, (string)o.Value);
  606. return nv;
  607. }
  608. private NameValueCollection CreateNV(Dictionary<string, object> d)
  609. {
  610. NameValueCollection nv = new NameValueCollection();
  611. foreach (var o in d)
  612. nv.Add(o.Key, (string)o.Value);
  613. return nv;
  614. }
  615. private void ProcessMap(object obj, Dictionary<string, myPropInfo> props, Dictionary<string, object> dic)
  616. {
  617. foreach (KeyValuePair<string, object> kv in dic)
  618. {
  619. myPropInfo p = props[kv.Key];
  620. object o = p.getter(obj);
  621. Type t = Type.GetType((string)kv.Value);
  622. if (t == typeof(Guid))
  623. p.setter(obj, CreateGuid((string)o));
  624. }
  625. }
  626. private int CreateInteger(string s, int index, int count)
  627. {
  628. int num = 0;
  629. bool neg = false;
  630. for (int x = 0; x < count; x++, index++)
  631. {
  632. char cc = s[index];
  633. if (cc == '-')
  634. neg = true;
  635. else if (cc == '+')
  636. neg = false;
  637. else
  638. {
  639. num *= 10;
  640. num += (int)(cc - '0');
  641. }
  642. }
  643. if (neg) num = -num;
  644. return num;
  645. }
  646. private object CreateEnum(Type pt, object v)
  647. {
  648. // TODO : optimize create enum
  649. #if !SILVERLIGHT
  650. return Enum.Parse(pt, v.ToString());
  651. #else
  652. return Enum.Parse(pt, v, true);
  653. #endif
  654. }
  655. private Guid CreateGuid(string s)
  656. {
  657. if (s.Length > 30)
  658. return new Guid(s);
  659. else
  660. return new Guid(Convert.FromBase64String(s));
  661. }
  662. private DateTime CreateDateTime(string value)
  663. {
  664. bool utc = false;
  665. // 0123456789012345678 9012 9/3
  666. // datetime format = yyyy-MM-ddTHH:mm:ss .nnn Z
  667. int year;
  668. int month;
  669. int day;
  670. int hour;
  671. int min;
  672. int sec;
  673. int ms = 0;
  674. year = CreateInteger(value, 0, 4);
  675. month = CreateInteger(value, 5, 2);
  676. day = CreateInteger(value, 8, 2);
  677. hour = CreateInteger(value, 11, 2);
  678. min = CreateInteger(value, 14, 2);
  679. sec = CreateInteger(value, 17, 2);
  680. if (value.Length > 21 && value[19] == '.')
  681. ms = CreateInteger(value, 20, 3);
  682. if (value[value.Length - 1] == 'Z')
  683. utc = true;
  684. if (_params.UseUTCDateTime == false && utc == false)
  685. return new DateTime(year, month, day, hour, min, sec, ms);
  686. else
  687. return new DateTime(year, month, day, hour, min, sec, ms, DateTimeKind.Utc).ToLocalTime();
  688. }
  689. private object CreateArray(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
  690. {
  691. Array col = Array.CreateInstance(bt, data.Count);
  692. // create an array of objects
  693. for (int i = 0; i < data.Count; i++)
  694. {
  695. object ob = data[i];
  696. if (ob == null)
  697. {
  698. continue;
  699. }
  700. if (ob is IDictionary)
  701. col.SetValue(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt, null), i);
  702. else if (ob is ICollection)
  703. col.SetValue(CreateArray((List<object>)ob, bt, bt.GetElementType(), globalTypes), i);
  704. else
  705. col.SetValue(ChangeType(ob, bt), i);
  706. }
  707. return col;
  708. }
  709. private object CreateGenericList(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
  710. {
  711. IList col = (IList)Reflection.Instance.FastCreateInstance(pt);
  712. // create an array of objects
  713. foreach (object ob in data)
  714. {
  715. if (ob is IDictionary)
  716. col.Add(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt, null));
  717. else if (ob is List<object>)
  718. {
  719. if (bt.IsGenericType)
  720. col.Add((List<object>)ob);//).ToArray());
  721. else
  722. col.Add(((List<object>)ob).ToArray());
  723. }
  724. else
  725. col.Add(ChangeType(ob, bt));
  726. }
  727. return col;
  728. }
  729. private object CreateStringKeyDictionary(Dictionary<string, object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
  730. {
  731. var col = (IDictionary)Reflection.Instance.FastCreateInstance(pt);
  732. Type t1 = null;
  733. Type t2 = null;
  734. if (types != null)
  735. {
  736. t1 = types[0];
  737. t2 = types[1];
  738. }
  739. foreach (KeyValuePair<string, object> values in reader)
  740. {
  741. var key = values.Key;
  742. object val = null;
  743. if (values.Value is Dictionary<string, object>)
  744. val = ParseDictionary((Dictionary<string, object>)values.Value, globalTypes, t2, null);
  745. else if (types != null && t2.IsArray)
  746. {
  747. if (values.Value is Array)
  748. val = values.Value;
  749. else
  750. val = CreateArray((List<object>)values.Value, t2, t2.GetElementType(), globalTypes);
  751. }
  752. else if (values.Value is IList)
  753. val = CreateGenericList((List<object>)values.Value, t2, t1, globalTypes);
  754. else
  755. val = ChangeType(values.Value, t2);
  756. col.Add(key, val);
  757. }
  758. return col;
  759. }
  760. private object CreateDictionary(List<object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
  761. {
  762. IDictionary col = (IDictionary)Reflection.Instance.FastCreateInstance(pt);
  763. Type t1 = null;
  764. Type t2 = null;
  765. if (types != null)
  766. {
  767. t1 = types[0];
  768. t2 = types[1];
  769. }
  770. foreach (Dictionary<string, object> values in reader)
  771. {
  772. object key = values["k"];
  773. object val = values["v"];
  774. if (key is Dictionary<string, object>)
  775. key = ParseDictionary((Dictionary<string, object>)key, globalTypes, t1, null);
  776. else
  777. key = ChangeType(key, t1);
  778. if (val is Dictionary<string, object>)
  779. val = ParseDictionary((Dictionary<string, object>)val, globalTypes, t2, null);
  780. else
  781. val = ChangeType(val, t2);
  782. col.Add(key, val);
  783. }
  784. return col;
  785. }
  786. #if !SILVERLIGHT
  787. private DataSet CreateDataset(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
  788. {
  789. DataSet ds = new DataSet();
  790. ds.EnforceConstraints = false;
  791. ds.BeginInit();
  792. // read dataset schema here
  793. var schema = reader["$schema"];
  794. if (schema is string)
  795. {
  796. TextReader tr = new StringReader((string)schema);
  797. ds.ReadXmlSchema(tr);
  798. }
  799. else
  800. {
  801. DatasetSchema ms = (DatasetSchema)ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema), null);
  802. ds.DataSetName = ms.Name;
  803. for (int i = 0; i < ms.Info.Count; i += 3)
  804. {
  805. if (ds.Tables.Contains(ms.Info[i]) == false)
  806. ds.Tables.Add(ms.Info[i]);
  807. ds.Tables[ms.Info[i]].Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
  808. }
  809. }
  810. foreach (KeyValuePair<string, object> pair in reader)
  811. {
  812. if (pair.Key == "$type" || pair.Key == "$schema") continue;
  813. List<object> rows = (List<object>)pair.Value;
  814. if (rows == null) continue;
  815. DataTable dt = ds.Tables[pair.Key];
  816. ReadDataTable(rows, dt);
  817. }
  818. ds.EndInit();
  819. return ds;
  820. }
  821. private void ReadDataTable(List<object> rows, DataTable dt)
  822. {
  823. dt.BeginInit();
  824. dt.BeginLoadData();
  825. List<int> guidcols = new List<int>();
  826. List<int> datecol = new List<int>();
  827. foreach (DataColumn c in dt.Columns)
  828. {
  829. if (c.DataType == typeof(Guid) || c.DataType == typeof(Guid?))
  830. guidcols.Add(c.Ordinal);
  831. if (_params.UseUTCDateTime && (c.DataType == typeof(DateTime) || c.DataType == typeof(DateTime?)))
  832. datecol.Add(c.Ordinal);
  833. }
  834. foreach (List<object> row in rows)
  835. {
  836. object[] v = new object[row.Count];
  837. row.CopyTo(v, 0);
  838. foreach (int i in guidcols)
  839. {
  840. string s = (string)v[i];
  841. if (s != null && s.Length < 36)
  842. v[i] = new Guid(Convert.FromBase64String(s));
  843. }
  844. if (_params.UseUTCDateTime)
  845. {
  846. foreach (int i in datecol)
  847. {
  848. string s = (string)v[i];
  849. if (s != null)
  850. v[i] = CreateDateTime(s);
  851. }
  852. }
  853. dt.Rows.Add(v);
  854. }
  855. dt.EndLoadData();
  856. dt.EndInit();
  857. }
  858. DataTable CreateDataTable(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
  859. {
  860. var dt = new DataTable();
  861. // read dataset schema here
  862. var schema = reader["$schema"];
  863. if (schema is string)
  864. {
  865. TextReader tr = new StringReader((string)schema);
  866. dt.ReadXmlSchema(tr);
  867. }
  868. else
  869. {
  870. var ms = (DatasetSchema)this.ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema), null);
  871. dt.TableName = ms.Info[0];
  872. for (int i = 0; i < ms.Info.Count; i += 3)
  873. {
  874. dt.Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
  875. }
  876. }
  877. foreach (var pair in reader)
  878. {
  879. if (pair.Key == "$type" || pair.Key == "$schema")
  880. continue;
  881. var rows = (List<object>)pair.Value;
  882. if (rows == null)
  883. continue;
  884. if (!dt.TableName.Equals(pair.Key, StringComparison.InvariantCultureIgnoreCase))
  885. continue;
  886. ReadDataTable(rows, dt);
  887. }
  888. return dt;
  889. }
  890. #endif
  891. #endregion
  892. }
  893. }