zoukankan      html  css  js  c++  java
  • JsonHelper

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Data;
    using System.Globalization;
    using System.IO;

    #if !SILVERLIGHT
    #endif

    namespace GT.Common.JsonHelper
    {
    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 = false;
    /// <summary>
    /// Serialize null values to the output (default = True)
    /// </summary>
    public bool SerializeNullValues = true;
    /// <summary>
    /// 是否采用严格的ISO日期 (default = false) by itdos.com
    /// </summary>
    public bool UseStrictIsoDate = false;
    /// <summary>
    /// 日期格式化 (default = "yyyy-MM-dd HH:mm:ss") by itdos.com
    /// </summary>
    public string DateFormatString = "yyyy-MM-dd HH:mm:ss";
    /// <summary>
    /// IsLiteral=false时是否序列化。(default = false)
    /// </summary>
    public bool UseFalseLiteral = false;
    /// <summary>
    /// Use the UTC date format (default = True)
    /// </summary>
    public bool UseUTCDateTime = false;
    /// <summary>
    /// Show the readonly properties of types in the output (default = False)
    /// </summary>
    public bool ShowReadOnlyProperties = true;
    /// <summary>
    /// Use the $types extension to optimise the output json (default = True)
    /// </summary>
    public bool UsingGlobalTypes = false;
    /// <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 = false;
    /// <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>
    /// 是否序列化DateTime毫秒。 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>
    /// DataTable类型是否默认序列化TableName (default = true) by itdos.com
    /// </summary>
    public bool DataTableToGeneralJson = true;

    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&lt;string,object&gt; or List&lt;object&gt; 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, null);// by itdos.com
    #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)
    {
    #region by itdos.com 2016-05-04
    var isNullOrWhiteSpace = false || (value == null || string.IsNullOrWhiteSpace(value.ToString()));
    if (conversionType == typeof(decimal))
    return isNullOrWhiteSpace ? (object)null : decimal.Parse(value.ToString());

    if (conversionType == typeof(int))
    return isNullOrWhiteSpace ? (object)null : int.Parse(value.ToString());

    else if (conversionType == typeof(long))
    return isNullOrWhiteSpace ? (object)null : long.Parse(value.ToString());

    else if (conversionType == typeof(string))
    return isNullOrWhiteSpace ? null : value.ToString();//by itdos.com 2016-05-09
    #endregion

    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)
    {
    //by itdos.com
    //case myPropInfoType.Int: oset = (int)((long)v); break;
    case myPropInfoType.Decimal: oset = decimal.Parse(v.ToString()); break;
    case myPropInfoType.Int: oset = int.Parse(string.IsNullOrWhiteSpace(v.ToString()) ? "0" : v.ToString()); break;
    //case myPropInfoType.Long: oset = (long)v; break;
    case myPropInfoType.Long: oset = long.Parse(v.ToString()); break;
    case myPropInfoType.String: oset = v.ToString(); break;// by itdos.com 2016-05-10
    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(v, globaltypes); break;// by itdos.com
    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)
    {
    // FEATURE : 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)
    {
    #region bi itdos.com 2015-05-01
    DateTime dt;
    if (DateTime.TryParse(value, out dt))
    {
    return dt;
    }
    #endregion
    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)
    {
    if (bt == null)
    bt = typeof(object);

    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(object o, Dictionary<string, object> globalTypes)// by itdos.com
    {
    var reader = o as Dictionary<string, object>;
    var dt = new DataTable();
    if (_params.DataTableToGeneralJson)
    {
    foreach (var k in (IList)o)
    {
    var dic = k as Dictionary<string, object>;
    var rows = new List<object>();
    var haveCol = dt.Columns.Count == 0;
    foreach (var o1 in dic)
    {
    if (haveCol)
    {
    if (o1.Value == null)
    {
    dt.Columns.Add(o1.Key);
    }
    else
    {
    dt.Columns.Add(o1.Key, o1.Value.GetType());
    }
    }
    rows.Add(o1.Value);
    }
    dt.Rows.Add(rows.ToArray());
    }
    return dt;
    }
    // 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
    }

    }

    萌橙 你瞅啥?
  • 相关阅读:
    SA练习题总结-篇一
    树上距离(树形DP)
    Codeforces Round #633(Div.2) E. Perfect Triples
    Codeforces Round #633 (Div. 2) D.Edge Weight Assignment
    问题 B: FZB(树形DP+边记忆化)
    【Matlab】自学笔记——基础知识篇
    【Python科学计算】Numpy——ndarry
    退役总结
    [树的遍历]树的遍历(PTA)
    [stl]集合相似度(PTA)
  • 原文地址:https://www.cnblogs.com/daimaxuejia/p/9772005.html
Copyright © 2011-2022 走看看