| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- #if !SILVERLIGHT
- using System.Data;
- #endif
- using System.Globalization;
- using System.IO;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Collections.Specialized;
- namespace FastJSON
- {
- public delegate string Serialize(object data);
- public delegate object Deserialize(string data);
- public sealed class JSONParameters
- {
- /// <summary>
- /// Use the optimized fast Dataset Schema format (default = True)
- /// </summary>
- public bool UseOptimizedDatasetSchema = true;
- /// <summary>
- /// Use the fast GUID format (default = True)
- /// </summary>
- public bool UseFastGuid = true;
- /// <summary>
- /// Serialize null values to the output (default = True)
- /// </summary>
- public bool SerializeNullValues = true;
- /// <summary>
- /// Use the UTC date format (default = True)
- /// </summary>
- public bool UseUTCDateTime = true;
- /// <summary>
- /// Show the readonly properties of types in the output (default = False)
- /// </summary>
- public bool ShowReadOnlyProperties = false;
- /// <summary>
- /// Use the $types extension to optimise the output json (default = True)
- /// </summary>
- public bool UsingGlobalTypes = true;
- /// <summary>
- /// Ignore case when processing json and deserializing
- /// </summary>
- [Obsolete("Not needed anymore and will always match")]
- public bool IgnoreCaseOnDeserialize = false;
- /// <summary>
- /// Anonymous types have read only properties
- /// </summary>
- public bool EnableAnonymousTypes = false;
- /// <summary>
- /// Enable fastJSON extensions $types, $type, $map (default = True)
- /// </summary>
- public bool UseExtensions = true;
- /// <summary>
- /// Use escaped unicode i.e. \uXXXX format for non ASCII characters (default = True)
- /// </summary>
- public bool UseEscapedUnicode = false;
- /// <summary>
- /// Output string key dictionaries as "k"/"v" format (default = False)
- /// </summary>
- public bool KVStyleStringDictionary = false;
- /// <summary>
- /// Output Enum values instead of names (default = False)
- /// </summary>
- public bool UseValuesOfEnums = false;
- /// <summary>
- /// Ignore attributes to check for (default : XmlIgnoreAttribute)
- /// </summary>
- public List<Type> IgnoreAttributes = new List<Type> { typeof(System.Xml.Serialization.XmlIgnoreAttribute) };
- /// <summary>
- /// If you have parametric and no default constructor for you classes (default = False)
- ///
- /// IMPORTANT NOTE : If True then all initial values within the class will be ignored and will be not set
- /// </summary>
- public bool ParametricConstructorOverride = false;
- /// <summary>
- /// Serialize DateTime milliseconds i.e. yyyy-MM-dd HH:mm:ss.nnn (default = false)
- /// </summary>
- public bool DateTimeMilliseconds = false;
- /// <summary>
- /// Maximum depth for circular references in inline mode (default = 20)
- /// </summary>
- public byte SerializerMaxDepth = 20;
- /// <summary>
- /// Inline circular or already seen objects instead of replacement with $i (default = False)
- /// </summary>
- public bool InlineCircularReferences = false;
- /// <summary>
- /// Save property/field names as lowercase (default = false)
- /// </summary>
- public bool SerializeToLowerCaseNames = false;
- /// <summary>
- /// Serialize property name with underline style
- /// </summary>
- public bool UseApiNamingStyle = false;
- public void FixValues()
- {
- if (UseExtensions == false) // disable conflicting params
- {
- UsingGlobalTypes = false;
- InlineCircularReferences = true;
- }
- if (EnableAnonymousTypes)
- ShowReadOnlyProperties = true;
- }
- }
- public static class JSON
- {
- /// <summary>
- /// Globally set-able parameters for controlling the serializer
- /// </summary>
- public static JSONParameters Parameters = new JSONParameters();
- /// <summary>
- /// Create a formatted json string (beautified) from an object
- /// </summary>
- /// <param name="obj"></param>
- /// <param name="param"></param>
- /// <returns></returns>
- public static string ToNiceJSON(object obj, JSONParameters param)
- {
- string s = ToJSON(obj, param);
- return Beautify(s);
- }
- /// <summary>
- /// Create a json representation for an object
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public static string ToJSON(object obj)
- {
- return ToJSON(obj, JSON.Parameters);
- }
- /// <summary>
- /// Create a json representation for an object with parameter override on this call
- /// </summary>
- /// <param name="obj"></param>
- /// <param name="param"></param>
- /// <returns></returns>
- public static string ToJSON(object obj, JSONParameters param)
- {
- param.FixValues();
- Type t = null;
- if (obj == null)
- return "null";
- if (obj.GetType().IsGenericType)
- t = Reflection.Instance.GetGenericTypeDefinition(obj.GetType());
- if (t == typeof(Dictionary<,>) || t == typeof(List<>))
- param.UsingGlobalTypes = false;
- // FEATURE : enable extensions when you can deserialize anon types
- if (param.EnableAnonymousTypes) { param.UseExtensions = false; param.UsingGlobalTypes = false; }
- return new JSONSerializer(param).ConvertToJSON(obj);
- }
- /// <summary>
- /// Parse a json string and generate a Dictionary<string,object> or List<object> structure
- /// </summary>
- /// <param name="json"></param>
- /// <returns></returns>
- public static object Parse(string json)
- {
- return new JsonParser(json).Decode();
- }
- #if net4
- /// <summary>
- /// Create a .net4 dynamic object from the json string
- /// </summary>
- /// <param name="json"></param>
- /// <returns></returns>
- public static dynamic ToDynamic(string json)
- {
- return new DynamicJson(json);
- }
- #endif
- /// <summary>
- /// Create a typed generic object from the json
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="json"></param>
- /// <returns></returns>
- public static T ToObject<T>(string json)
- {
- return new deserializer(Parameters).ToObject<T>(json);
- }
- /// <summary>
- /// Create a typed generic object from the json with parameter override on this call
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="json"></param>
- /// <param name="param"></param>
- /// <returns></returns>
- public static T ToObject<T>(string json, JSONParameters param)
- {
- return new deserializer(param).ToObject<T>(json);
- }
- /// <summary>
- /// Create an object from the json
- /// </summary>
- /// <param name="json"></param>
- /// <returns></returns>
- public static object ToObject(string json)
- {
- return new deserializer(Parameters).ToObject(json, null);
- }
- /// <summary>
- /// Create an object from the json with parameter override on this call
- /// </summary>
- /// <param name="json"></param>
- /// <param name="param"></param>
- /// <returns></returns>
- public static object ToObject(string json, JSONParameters param)
- {
- return new deserializer(param).ToObject(json, null);
- }
- /// <summary>
- /// Create an object of type from the json
- /// </summary>
- /// <param name="json"></param>
- /// <param name="type"></param>
- /// <returns></returns>
- public static object ToObject(string json, Type type)
- {
- return new deserializer(Parameters).ToObject(json, type);
- }
- /// <summary>
- /// Fill a given object with the json represenation
- /// </summary>
- /// <param name="input"></param>
- /// <param name="json"></param>
- /// <returns></returns>
- public static object FillObject(object input, string json)
- {
- Dictionary<string, object> ht = new JsonParser(json).Decode() as Dictionary<string, object>;
- if (ht == null) return null;
- return new deserializer(Parameters).ParseDictionary(ht, null, input.GetType(), input);
- }
- /// <summary>
- /// Deep copy an object i.e. clone to a new object
- /// </summary>
- /// <param name="obj"></param>
- /// <returns></returns>
- public static object DeepCopy(object obj)
- {
- return new deserializer(Parameters).ToObject(ToJSON(obj));
- }
- /// <summary>
- ///
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="obj"></param>
- /// <returns></returns>
- public static T DeepCopy<T>(T obj)
- {
- return new deserializer(Parameters).ToObject<T>(ToJSON(obj));
- }
- /// <summary>
- /// Create a human readable string from the json
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- public static string Beautify(string input)
- {
- return Formatter.PrettyPrint(input);
- }
- /// <summary>
- /// Register custom type handlers for your own types not natively handled by fastJSON
- /// </summary>
- /// <param name="type"></param>
- /// <param name="serializer"></param>
- /// <param name="deserializer"></param>
- public static void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer)
- {
- Reflection.Instance.RegisterCustomType(type, serializer, deserializer);
- }
- /// <summary>
- /// Clear the internal reflection cache so you can start from new (you will loose performance)
- /// </summary>
- public static void ClearReflectionCache()
- {
- Reflection.Instance.ClearReflectionCache();
- }
- internal static long CreateLong(out long num, string s, int index, int count)
- {
- num = 0;
- bool neg = false;
- for (int x = 0; x < count; x++, index++)
- {
- char cc = s[index];
- if (cc == '-')
- neg = true;
- else if (cc == '+')
- neg = false;
- else
- {
- num *= 10;
- num += (int)(cc - '0');
- }
- }
- if (neg) num = -num;
- return num;
- }
- }
- internal class deserializer
- {
- public deserializer(JSONParameters param)
- {
- _params = param;
- }
- private JSONParameters _params;
- private bool _usingglobals = false;
- private Dictionary<object, int> _circobj = new Dictionary<object, int>();
- private Dictionary<int, object> _cirrev = new Dictionary<int, object>();
- public T ToObject<T>(string json)
- {
- Type t = typeof(T);
- var o = ToObject(json, t);
- if (t.IsArray)
- {
- if ((o as ICollection).Count == 0) // edge case for "[]" -> T[]
- {
- Type tt = t.GetElementType();
- object oo = Array.CreateInstance(tt, 0);
- return (T)oo;
- }
- else
- return (T)o;
- }
- else
- return (T)o;
- }
- public object ToObject(string json)
- {
- return ToObject(json, null);
- }
- public object ToObject(string json, Type type)
- {
- //_params = Parameters;
- _params.FixValues();
- Type t = null;
- if (type != null && type.IsGenericType)
- t = Reflection.Instance.GetGenericTypeDefinition(type);
- if (t == typeof(Dictionary<,>) || t == typeof(List<>))
- _params.UsingGlobalTypes = false;
- _usingglobals = _params.UsingGlobalTypes;
- object o = new JsonParser(json).Decode();
- if (o == null)
- return null;
- #if !SILVERLIGHT
- if (type != null && type == typeof(DataSet))
- return CreateDataset(o as Dictionary<string, object>, null);
- else if (type != null && type == typeof(DataTable))
- return CreateDataTable(o as Dictionary<string, object>, null);
- #endif
- if (o is IDictionary)
- {
- if (type != null && t == typeof(Dictionary<,>)) // deserialize a dictionary
- return RootDictionary(o, type);
- else // deserialize an object
- return ParseDictionary(o as Dictionary<string, object>, null, type, null);
- }
- else if (o is List<object>)
- {
- if (type != null && t == typeof(Dictionary<,>)) // kv format
- return RootDictionary(o, type);
- else if (type != null && t == typeof(List<>)) // deserialize to generic list
- return RootList(o, type);
- else if (type == typeof(Hashtable))
- return RootHashTable((List<object>)o);
- else
- return (o as List<object>).ToArray();
- }
- else if (type != null && o.GetType() != type)
- return ChangeType(o, type);
- return o;
- }
- #region [ p r i v a t e m e t h o d s ]
- private object RootHashTable(List<object> o)
- {
- Hashtable h = new Hashtable();
- foreach (Dictionary<string, object> values in o)
- {
- object key = values["k"];
- object val = values["v"];
- if (key is Dictionary<string, object>)
- key = ParseDictionary((Dictionary<string, object>)key, null, typeof(object), null);
- if (val is Dictionary<string, object>)
- val = ParseDictionary((Dictionary<string, object>)val, null, typeof(object), null);
- h.Add(key, val);
- }
- return h;
- }
- private object ChangeType(object value, Type conversionType)
- {
- if (conversionType == typeof(int))
- return (int)((long)value);
- else if (conversionType == typeof(long))
- return (long)value;
- else if (conversionType == typeof(string))
- return (string)value;
- else if (conversionType.IsEnum)
- return CreateEnum(conversionType, value);
- else if (conversionType == typeof(DateTime))
- return CreateDateTime((string)value);
- else if (Reflection.Instance.IsTypeRegistered(conversionType))
- return Reflection.Instance.CreateCustom((string)value, conversionType);
- // 8-30-2014 - James Brooks - Added code for nullable types.
- if (IsNullable(conversionType))
- {
- if (value == null)
- {
- return value;
- }
- conversionType = UnderlyingTypeOf(conversionType);
- }
- // 8-30-2014 - James Brooks - Nullable Guid is a special case so it was moved after the "IsNullable" check.
- if (conversionType == typeof(Guid))
- return CreateGuid((string)value);
- return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture);
- }
- private bool IsNullable(Type t)
- {
- if (!t.IsGenericType) return false;
- Type g = t.GetGenericTypeDefinition();
- return (g.Equals(typeof(Nullable<>)));
- }
- private Type UnderlyingTypeOf(Type t)
- {
- return t.GetGenericArguments()[0];
- }
- private object RootList(object parse, Type type)
- {
- Type[] gtypes = Reflection.Instance.GetGenericArguments(type);
- IList o = (IList)Reflection.Instance.FastCreateInstance(type);
- foreach (var k in (IList)parse)
- {
- _usingglobals = false;
- object v = k;
- if (k is Dictionary<string, object>)
- v = ParseDictionary(k as Dictionary<string, object>, null, gtypes[0], null);
- else
- v = ChangeType(k, gtypes[0]);
- o.Add(v);
- }
- return o;
- }
- private object RootDictionary(object parse, Type type)
- {
- Type[] gtypes = Reflection.Instance.GetGenericArguments(type);
- Type t1 = null;
- Type t2 = null;
- if (gtypes != null)
- {
- t1 = gtypes[0];
- t2 = gtypes[1];
- }
- if (parse is Dictionary<string, object>)
- {
- IDictionary o = (IDictionary)Reflection.Instance.FastCreateInstance(type);
- foreach (var kv in (Dictionary<string, object>)parse)
- {
- object v;
- object k = ChangeType(kv.Key, t1);
- if (kv.Value is Dictionary<string, object>)
- v = ParseDictionary(kv.Value as Dictionary<string, object>, null, t2, null);
- else if (t2.IsArray)
- v = CreateArray((List<object>)kv.Value, t2, t2.GetElementType(), null);
- else if (kv.Value is IList)
- v = CreateGenericList((List<object>)kv.Value, t2, t1, null);
- else
- v = ChangeType(kv.Value, t2);
- o.Add(k, v);
- }
- return o;
- }
- if (parse is List<object>)
- return CreateDictionary(parse as List<object>, type, gtypes, null);
- return null;
- }
- internal object ParseDictionary(Dictionary<string, object> d, Dictionary<string, object> globaltypes, Type type, object input)
- {
- object tn = "";
- if (type == typeof(NameValueCollection))
- return CreateNV(d);
- if (type == typeof(StringDictionary))
- return CreateSD(d);
- if (d.TryGetValue("$i", out tn))
- {
- object v = null;
- _cirrev.TryGetValue((int)(long)tn, out v);
- return v;
- }
- if (d.TryGetValue("$types", out tn))
- {
- _usingglobals = true;
- globaltypes = new Dictionary<string, object>();
- foreach (var kv in (Dictionary<string, object>)tn)
- {
- globaltypes.Add((string)kv.Value, kv.Key);
- }
- }
- bool found = d.TryGetValue("$type", out tn);
- #if !SILVERLIGHT
- if (found == false && type == typeof(System.Object))
- {
- return d; // CreateDataset(d, globaltypes);
- }
- #endif
- if (found)
- {
- if (_usingglobals)
- {
- object tname = "";
- if (globaltypes != null && globaltypes.TryGetValue((string)tn, out tname))
- tn = tname;
- }
- type = Reflection.Instance.GetTypeFromCache((string)tn);
- }
- if (type == null)
- throw new Exception("Cannot determine type");
- string typename = type.FullName;
- object o = input;
- if (o == null)
- {
- if (_params.ParametricConstructorOverride)
- o = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type);
- else
- o = Reflection.Instance.FastCreateInstance(type);
- }
- int circount = 0;
- if (_circobj.TryGetValue(o, out circount) == false)
- {
- circount = _circobj.Count + 1;
- _circobj.Add(o, circount);
- _cirrev.Add(circount, o);
- }
- Dictionary<string, myPropInfo> props = Reflection.Instance.Getproperties(type, typename, Reflection.Instance.IsTypeRegistered(type));
- foreach (var kv in d)
- {
- var n = kv.Key;
- var v = kv.Value;
- string name = n.ToLower();
- if (name == "$map")
- {
- ProcessMap(o, props, (Dictionary<string, object>)d[name]);
- continue;
- }
- myPropInfo pi;
- if (props.TryGetValue(name, out pi) == false)
- continue;
- if (pi.CanWrite)
- {
- //object v = d[n];
- if (v != null)
- {
- object oset = null;
- switch (pi.Type)
- {
- case myPropInfoType.Int: oset = (int)((long)v); break;
- case myPropInfoType.Long: oset = (long)v; break;
- case myPropInfoType.String: oset = (string)v; break;
- case myPropInfoType.Bool: oset = (bool)v; break;
- case myPropInfoType.DateTime: oset = CreateDateTime((string)v); break;
- case myPropInfoType.Enum: oset = CreateEnum(pi.pt, v); break;
- case myPropInfoType.Guid: oset = CreateGuid((string)v); break;
- case myPropInfoType.Array:
- if (!pi.IsValueType)
- oset = CreateArray((List<object>)v, pi.pt, pi.bt, globaltypes);
- // what about 'else'?
- break;
- case myPropInfoType.ByteArray: oset = Convert.FromBase64String((string)v); break;
- #if !SILVERLIGHT
- case myPropInfoType.DataSet: oset = CreateDataset((Dictionary<string, object>)v, globaltypes); break;
- case myPropInfoType.DataTable: oset = CreateDataTable((Dictionary<string, object>)v, globaltypes); break;
- case myPropInfoType.Hashtable: // same case as Dictionary
- #endif
- case myPropInfoType.Dictionary: oset = CreateDictionary((List<object>)v, pi.pt, pi.GenericTypes, globaltypes); break;
- case myPropInfoType.StringKeyDictionary: oset = CreateStringKeyDictionary((Dictionary<string, object>)v, pi.pt, pi.GenericTypes, globaltypes); break;
- case myPropInfoType.NameValue: oset = CreateNV((Dictionary<string, object>)v); break;
- case myPropInfoType.StringDictionary: oset = CreateSD((Dictionary<string, object>)v); break;
- case myPropInfoType.Custom: oset = Reflection.Instance.CreateCustom((string)v, pi.pt); break;
- default:
- {
- if (pi.IsGenericType && pi.IsValueType == false && v is List<object>)
- oset = CreateGenericList((List<object>)v, pi.pt, pi.bt, globaltypes);
- else if ((pi.IsClass || pi.IsStruct) && v is Dictionary<string, object>)
- oset = ParseDictionary((Dictionary<string, object>)v, globaltypes, pi.pt, pi.getter(o));
- else if (v is List<object>)
- oset = CreateArray((List<object>)v, pi.pt, typeof(object), globaltypes);
- else if (pi.IsValueType)
- oset = ChangeType(v, pi.changeType);
- else
- oset = v;
- }
- break;
- }
- o = pi.setter(o, oset);
- }
- }
- }
- return o;
- }
- private StringDictionary CreateSD(Dictionary<string, object> d)
- {
- StringDictionary nv = new StringDictionary();
- foreach (var o in d)
- nv.Add(o.Key, (string)o.Value);
- return nv;
- }
- private NameValueCollection CreateNV(Dictionary<string, object> d)
- {
- NameValueCollection nv = new NameValueCollection();
- foreach (var o in d)
- nv.Add(o.Key, (string)o.Value);
- return nv;
- }
- private void ProcessMap(object obj, Dictionary<string, myPropInfo> props, Dictionary<string, object> dic)
- {
- foreach (KeyValuePair<string, object> kv in dic)
- {
- myPropInfo p = props[kv.Key];
- object o = p.getter(obj);
- Type t = Type.GetType((string)kv.Value);
- if (t == typeof(Guid))
- p.setter(obj, CreateGuid((string)o));
- }
- }
- private int CreateInteger(string s, int index, int count)
- {
- int num = 0;
- bool neg = false;
- for (int x = 0; x < count; x++, index++)
- {
- char cc = s[index];
- if (cc == '-')
- neg = true;
- else if (cc == '+')
- neg = false;
- else
- {
- num *= 10;
- num += (int)(cc - '0');
- }
- }
- if (neg) num = -num;
- return num;
- }
- private object CreateEnum(Type pt, object v)
- {
- // TODO : optimize create enum
- #if !SILVERLIGHT
- return Enum.Parse(pt, v.ToString());
- #else
- return Enum.Parse(pt, v, true);
- #endif
- }
- private Guid CreateGuid(string s)
- {
- if (s.Length > 30)
- return new Guid(s);
- else
- return new Guid(Convert.FromBase64String(s));
- }
- private DateTime CreateDateTime(string value)
- {
- bool utc = false;
- // 0123456789012345678 9012 9/3
- // datetime format = yyyy-MM-ddTHH:mm:ss .nnn Z
- int year;
- int month;
- int day;
- int hour;
- int min;
- int sec;
- int ms = 0;
- year = CreateInteger(value, 0, 4);
- month = CreateInteger(value, 5, 2);
- day = CreateInteger(value, 8, 2);
- hour = CreateInteger(value, 11, 2);
- min = CreateInteger(value, 14, 2);
- sec = CreateInteger(value, 17, 2);
- if (value.Length > 21 && value[19] == '.')
- ms = CreateInteger(value, 20, 3);
- if (value[value.Length - 1] == 'Z')
- utc = true;
- if (_params.UseUTCDateTime == false && utc == false)
- return new DateTime(year, month, day, hour, min, sec, ms);
- else
- return new DateTime(year, month, day, hour, min, sec, ms, DateTimeKind.Utc).ToLocalTime();
- }
- private object CreateArray(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
- {
- Array col = Array.CreateInstance(bt, data.Count);
- // create an array of objects
- for (int i = 0; i < data.Count; i++)
- {
- object ob = data[i];
- if (ob == null)
- {
- continue;
- }
- if (ob is IDictionary)
- col.SetValue(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt, null), i);
- else if (ob is ICollection)
- col.SetValue(CreateArray((List<object>)ob, bt, bt.GetElementType(), globalTypes), i);
- else
- col.SetValue(ChangeType(ob, bt), i);
- }
- return col;
- }
- private object CreateGenericList(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes)
- {
- IList col = (IList)Reflection.Instance.FastCreateInstance(pt);
- // create an array of objects
- foreach (object ob in data)
- {
- if (ob is IDictionary)
- col.Add(ParseDictionary((Dictionary<string, object>)ob, globalTypes, bt, null));
- else if (ob is List<object>)
- {
- if (bt.IsGenericType)
- col.Add((List<object>)ob);//).ToArray());
- else
- col.Add(((List<object>)ob).ToArray());
- }
- else
- col.Add(ChangeType(ob, bt));
- }
- return col;
- }
- private object CreateStringKeyDictionary(Dictionary<string, object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
- {
- var col = (IDictionary)Reflection.Instance.FastCreateInstance(pt);
- Type t1 = null;
- Type t2 = null;
- if (types != null)
- {
- t1 = types[0];
- t2 = types[1];
- }
- foreach (KeyValuePair<string, object> values in reader)
- {
- var key = values.Key;
- object val = null;
- if (values.Value is Dictionary<string, object>)
- val = ParseDictionary((Dictionary<string, object>)values.Value, globalTypes, t2, null);
- else if (types != null && t2.IsArray)
- {
- if (values.Value is Array)
- val = values.Value;
- else
- val = CreateArray((List<object>)values.Value, t2, t2.GetElementType(), globalTypes);
- }
- else if (values.Value is IList)
- val = CreateGenericList((List<object>)values.Value, t2, t1, globalTypes);
- else
- val = ChangeType(values.Value, t2);
- col.Add(key, val);
- }
- return col;
- }
- private object CreateDictionary(List<object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes)
- {
- IDictionary col = (IDictionary)Reflection.Instance.FastCreateInstance(pt);
- Type t1 = null;
- Type t2 = null;
- if (types != null)
- {
- t1 = types[0];
- t2 = types[1];
- }
- foreach (Dictionary<string, object> values in reader)
- {
- object key = values["k"];
- object val = values["v"];
- if (key is Dictionary<string, object>)
- key = ParseDictionary((Dictionary<string, object>)key, globalTypes, t1, null);
- else
- key = ChangeType(key, t1);
- if (val is Dictionary<string, object>)
- val = ParseDictionary((Dictionary<string, object>)val, globalTypes, t2, null);
- else
- val = ChangeType(val, t2);
- col.Add(key, val);
- }
- return col;
- }
- #if !SILVERLIGHT
- private DataSet CreateDataset(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
- {
- DataSet ds = new DataSet();
- ds.EnforceConstraints = false;
- ds.BeginInit();
- // read dataset schema here
- var schema = reader["$schema"];
- if (schema is string)
- {
- TextReader tr = new StringReader((string)schema);
- ds.ReadXmlSchema(tr);
- }
- else
- {
- DatasetSchema ms = (DatasetSchema)ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema), null);
- ds.DataSetName = ms.Name;
- for (int i = 0; i < ms.Info.Count; i += 3)
- {
- if (ds.Tables.Contains(ms.Info[i]) == false)
- ds.Tables.Add(ms.Info[i]);
- ds.Tables[ms.Info[i]].Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
- }
- }
- foreach (KeyValuePair<string, object> pair in reader)
- {
- if (pair.Key == "$type" || pair.Key == "$schema") continue;
- List<object> rows = (List<object>)pair.Value;
- if (rows == null) continue;
- DataTable dt = ds.Tables[pair.Key];
- ReadDataTable(rows, dt);
- }
- ds.EndInit();
- return ds;
- }
- private void ReadDataTable(List<object> rows, DataTable dt)
- {
- dt.BeginInit();
- dt.BeginLoadData();
- List<int> guidcols = new List<int>();
- List<int> datecol = new List<int>();
- foreach (DataColumn c in dt.Columns)
- {
- if (c.DataType == typeof(Guid) || c.DataType == typeof(Guid?))
- guidcols.Add(c.Ordinal);
- if (_params.UseUTCDateTime && (c.DataType == typeof(DateTime) || c.DataType == typeof(DateTime?)))
- datecol.Add(c.Ordinal);
- }
- foreach (List<object> row in rows)
- {
- object[] v = new object[row.Count];
- row.CopyTo(v, 0);
- foreach (int i in guidcols)
- {
- string s = (string)v[i];
- if (s != null && s.Length < 36)
- v[i] = new Guid(Convert.FromBase64String(s));
- }
- if (_params.UseUTCDateTime)
- {
- foreach (int i in datecol)
- {
- string s = (string)v[i];
- if (s != null)
- v[i] = CreateDateTime(s);
- }
- }
- dt.Rows.Add(v);
- }
- dt.EndLoadData();
- dt.EndInit();
- }
- DataTable CreateDataTable(Dictionary<string, object> reader, Dictionary<string, object> globalTypes)
- {
- var dt = new DataTable();
- // read dataset schema here
- var schema = reader["$schema"];
- if (schema is string)
- {
- TextReader tr = new StringReader((string)schema);
- dt.ReadXmlSchema(tr);
- }
- else
- {
- var ms = (DatasetSchema)this.ParseDictionary((Dictionary<string, object>)schema, globalTypes, typeof(DatasetSchema), null);
- dt.TableName = ms.Info[0];
- for (int i = 0; i < ms.Info.Count; i += 3)
- {
- dt.Columns.Add(ms.Info[i + 1], Type.GetType(ms.Info[i + 2]));
- }
- }
- foreach (var pair in reader)
- {
- if (pair.Key == "$type" || pair.Key == "$schema")
- continue;
- var rows = (List<object>)pair.Value;
- if (rows == null)
- continue;
- if (!dt.TableName.Equals(pair.Key, StringComparison.InvariantCultureIgnoreCase))
- continue;
- ReadDataTable(rows, dt);
- }
- return dt;
- }
- #endif
- #endregion
- }
- }
|