예제 #1
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            Type underlying_type = Nullable.GetUnderlyingType(inst_type);
            Type value_type      = underlying_type ?? inst_type;

            if (reader.Token == JsonToken.Null)
            {
                #if NETSTANDARD1_5
                if (inst_type.IsClass() || underlying_type != null)
                {
                    return(null);
                }
                #else
                if (inst_type.IsClass || underlying_type != null)
                {
                    return(null);
                }
                #endif

                throw new JsonException(String.Format(
                                            "Can't assign null to an instance of type {0}",
                                            inst_type));
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (value_type.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }

                // If there's a custom importer that fits, use it
                if (custom_importers_table.ContainsKey(json_type) &&
                    custom_importers_table[json_type].ContainsKey(
                        value_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][value_type];

                    return(importer(reader.Value));
                }

                // Maybe there's a base importer that works
                if (base_importers_table.ContainsKey(json_type) &&
                    base_importers_table[json_type].ContainsKey(
                        value_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][value_type];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                #if NETSTANDARD1_5
                if (value_type.IsEnum())
                {
                    return(Enum.ToObject(value_type, reader.Value));
                }
                #else
                if (value_type.IsEnum)
                {
                    return(Enum.ToObject(value_type, reader.Value));
                }
                #endif
                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(value_type, json_type);

                if (conv_op != null)
                {
                    return(conv_op.Invoke(null,
                                          new object[] { reader.Value }));
                }

                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type, inst_type));
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }

                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(value_type);
                ObjectMetadata t_data = object_metadata[value_type];

                instance = Activator.CreateInstance(value_type);

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    string property = (string)reader.Value;

                    if (t_data.Properties.ContainsKey(property))
                    {
                        PropertyMetadata prop_data =
                            t_data.Properties[property];

                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(
                                instance, ReadValue(prop_data.Type, reader));
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader),
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        ((IDictionary)instance).Add(
                            property, ReadValue(
                                t_data.ElementType, reader));
                    }
                }
            }

            return(instance);
        }
예제 #2
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.IsClass || underlying_type != null)
                {
                    return(null);
                }

                throw new JsonException(String.Format(
                                            "Can't assign null to an instance of type {0}",
                                            inst_type));
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();
                var  vt        = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type;

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte))
                    {
                        return(reader.Value);
                    }
                }
                // If there's a custom importer that fits, use it
                if (custom_importers_table.ContainsKey(json_type) &&
                    custom_importers_table[json_type].ContainsKey(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

                // Maybe there's a base importer that works
                if (base_importers_table.ContainsKey(json_type) &&
                    base_importers_table[json_type].ContainsKey(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                if (vt.IsEnum)
                {
                    return(Enum.ToObject(vt, reader.Value));
                }

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(vt, json_type);

                if (conv_op != null)
                {
                    return(conv_op.Invoke(null,
                                          new object[] { reader.Value }));
                }

                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type, inst_type));
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type;
                    if (elem_type is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.IsEnum)
                    {
                        item = (int)item;
                    }
                    else
                    {
                        item = rt.CheckCLRTypes(item);
                    }
                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(value_type);
                ObjectMetadata t_data = object_metadata[value_type];
                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    instance = Activator.CreateInstance(value_type);
                }
                bool isIntKey = t_data.IsDictionary && value_type.GetGenericArguments()[0] == typeof(int);

                var hotArguments = (inst_type as ILRuntimeWrapperType)?.CLRType.GenericArguments?
                                   .Select(i => i.Value)
                                   .ToList()
                                   .FindAll(t => !(t is CLRType));

                var valid = hotArguments?.Count == 1;

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    string key = (string)reader.Value;

                    if (t_data.Properties.ContainsKey(key))
                    {
                        PropertyMetadata prop_data =
                            t_data.Properties[key];

                        if (prop_data.IsField)
                        {
                            var val      = ((FieldInfo)prop_data.Info);
                            var realType = prop_data.Type;
                            if (val.FieldType.ToString() == "ILRuntime.Runtime.Intepreter.ILTypeInstance")
                            {
                                //支持一下本地泛型<热更类型>,这种属于CLRType,会new ILTypeIns导致错误
                                //这里要做的就是把泛型参数里面的热更类型获取出来
                                //但如果有超过1个热更类型在参数里,就没办法判断哪个是这个字段的ILTypeIns了,所以只能1个
                                if (!valid)
                                {
                                    throw new NotSupportedException("仅支持解析1个热更类型做泛型参数的本地泛型类");
                                }

                                realType = hotArguments[0].ReflectionType;
                            }

                            ((FieldInfo)prop_data.Info).SetValue(
                                instance, ReadValue(realType, reader));
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            var val      = ((PropertyInfo)prop_data.Info);
                            var realType = prop_data.Type;
                            if (val.PropertyType.ToString() == "ILRuntime.Runtime.Intepreter.ILTypeInstance")
                            {
                                if (!valid)
                                {
                                    throw new NotSupportedException("仅支持解析1个热更类型做泛型参数的本地泛型类");
                                }

                                realType = hotArguments[0].ReflectionType;
                            }

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(realType, reader),
                                    null);
                            }
                            else
                            {
                                ReadValue(realType, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, key));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        var    dict      = ((IDictionary)instance);
                        var    elem_type = t_data.ElementType;
                        object readValue = ReadValue(elem_type, reader);
                        var    rt        = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType
                            ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType
                            : t_data.ElementType;
                        //value 是枚举的情况没处理,毕竟少
                        if (isIntKey)
                        {
                            var          dictValueType = value_type.GetGenericArguments()[1];
                            IConvertible convertible   = dictValueType as IConvertible;
                            if (convertible == null)
                            {
                                //自定义类型扩展
                                if (dictValueType == typeof(double)) //CheckCLRTypes() 没有double,也可以修改ilruntime源码实现
                                {
                                    var v = Convert.ChangeType(readValue.ToString(), dictValueType);
                                    dict.Add(Convert.ToInt32(key), v);
                                }
                                else
                                {
                                    readValue = rt.CheckCLRTypes(readValue);
                                    dict.Add(Convert.ToInt32(key), readValue);
                                    // throw new JsonException (String.Format("The type {0} doesn't not support",dictValueType));
                                }
                            }
                            else
                            {
                                var v = Convert.ChangeType(readValue, dictValueType);
                                dict.Add(Convert.ToInt32(key), v);
                            }
                        }
                        else
                        {
                            readValue = rt.CheckCLRTypes(readValue);
                            dict.Add(key, readValue);
                        }
                    }
                }
            }

            return(instance);
        }
예제 #3
0
        private static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
            {
                data.IsDictionary = true;
            }

            data.Properties = new Dictionary <string, PropertyMetadata> ();

            foreach (PropertyInfo p_info in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                if (p_info.Name == "Item")
                {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length == 1)
                    {
                        if (parameters[0].ParameterType == typeof(string))
                        {
                            data.ElementType = p_info.PropertyType;
                        }

                        continue;
                    }

                    if (parameters.Length > 1)
                    {
                        continue;
                    }
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                if (p_info.IsDefined(typeof(JsonPropertyName), true))
                {
                    var att = (JsonPropertyName)p_info.GetCustomAttributes(typeof(JsonPropertyName), true)[0];
                    data.Properties.Add(att.Name, p_data);
                }
                else
                {
                    data.Properties.Add(p_info.Name, p_data);
                }
            }

            foreach (FieldInfo f_info in type.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                if (f_info.IsDefined(typeof(JsonPropertyName), true))
                {
                    var att = (JsonPropertyName)f_info.GetCustomAttributes(typeof(JsonPropertyName), true)[0];
                    data.Properties.Add(att.Name, p_data);
                }
                else
                {
                    data.Properties.Add(f_info.Name, p_data);
                }
            }

            lock (object_metadata_lock) {
                try {
                    object_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #4
0
        private static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
            {
                data.IsDictionary = true;
            }

            data.Properties = new Dictionary <string, PropertyMetadata> ();

            foreach (PropertyInfo p_info in type.GetProperties())
            {
                if (p_info.Name == "Item")
                {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    if (parameters[0].ParameterType == typeof(string))
                    {
                        data.ElementType = p_info.PropertyType;
                    }

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                ProcessAttributes(ref p_data, p_info);

                data.Properties.Add(p_info.Name, p_data);
            }

            foreach (FieldInfo f_info in type.GetFields())
            {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                ProcessAttributes(ref p_data, f_info);

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock) {
                try {
                    object_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #5
0
        private static object ReadValue(Type inst_type, JsonReader reader, bool usingTypeInfo = false)
        {
            reader.Read();

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (inst_type.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }

                // If there's a custom importer that fits, use it
                if (custom_importers_table.ContainsKey(json_type) &&
                    custom_importers_table[json_type].ContainsKey(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

                // Maybe there's a base importer that works
                if (base_importers_table.ContainsKey(json_type) &&
                    base_importers_table[json_type].ContainsKey(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                if (inst_type.IsEnum)
                {
                    return(Enum.ToObject(inst_type, reader.Value));
                }

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_type, json_type);

                if (conv_op != null)
                {
                    return(conv_op.Invoke(null,
                                          new object[] { reader.Value }));
                }

                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type, inst_type));
            }

            object instance = null;

            #region read array
            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader, usingTypeInfo);
                    if (reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }

                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            #endregion
            #region read object
            else if (reader.Token == JsonToken.ObjectStart)
            {
                // if we are using type info we expect the type name as first field in the json
                bool peekedForType = false;
                if (usingTypeInfo && !IsDictionary(inst_type))
                {
                    reader.Read();

                    if ((string)reader.Value == keyTypeInfo)
                    {
                        string t = (string)ReadValue(typeof(System.String), reader);
                        inst_type = Type.GetType(t);
                    }
                    else
                    {
                        // remember that we already read the next member's name
                        peekedForType = true;
                    }
                }

                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_type);

                while (true)
                {
                    // we already read ahead if we didn't find type info
                    if (!peekedForType)
                    {
                        reader.Read();
                    }
                    else
                    {
                        peekedForType = false;
                    }

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    string property = (string)reader.Value;

                    if (t_data.Properties.ContainsKey(property))
                    {
                        PropertyMetadata prop_data =
                            t_data.Properties[property];

                        // Don't deserialize a field or property that has a JsonIgnore attribute with deserialization usage.
                        if ((prop_data.Ignore & JsonIgnoreWhen.Deserializing) > 0)
                        {
                            reader.Read();
                            continue;
                        }

                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(
                                instance, ReadValue(prop_data.Type, reader, usingTypeInfo));
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader, usingTypeInfo),
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader, usingTypeInfo);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            reader.Read();
                            if (reader.Token == JsonToken.ObjectStart)
                            {
                                while (reader.Token != JsonToken.ObjectEnd)
                                {
                                    reader.Read();
                                }
                            }
                            continue;
                        }
                        // TODO throw exception and return result as part of the exception
//                            throw new JsonException (String.Format (
//                                    "The type {0} doesn't have the " +
//                                    "property '{1}'", inst_type, property));
                        else
                        {
                            ((IDictionary)instance).Add(
                                property, ReadValue(
                                    t_data.ElementType, reader, usingTypeInfo));
                        }
                    }
                }
            }
            #endregion

            return(instance);
        }
예제 #6
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read(inst_type);

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            if (reader.Token == JsonToken.Null)
            {
                if (!inst_type.IsClass)
                {
                    throw new JsonException(String.Format(
                                                "Can't assign null to an instance of type {0}",
                                                inst_type));
                }

                return(null);
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();

                if (inst_type.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }

                // If there's a custom importer that fits, use it
                if (custom_importers_table.ContainsKey(json_type) &&
                    custom_importers_table[json_type].ContainsKey(
                        inst_type))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

                // Maybe there's a base importer that works
                if (base_importers_table.ContainsKey(json_type) &&
                    base_importers_table[json_type].ContainsKey(
                        inst_type))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][inst_type];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                if (inst_type.IsEnum)
                {
                    return(Enum.ToObject(inst_type, reader.Value));
                }

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(inst_type, json_type);

                if (conv_op != null)
                {
                    return(conv_op.Invoke(null,
                                          new object[] { reader.Value }));
                }

                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type, inst_type));
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }

                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];



                reader.Read();


                //如果打开自动识别类型,那么就可以支持已经定义的动态类型
                var  AttrList   = inst_type.GetCustomAttributes(typeof(LitJsonObjectAttribute), false);
                bool NoSelfType = false;
                foreach (var attr in AttrList)
                {
                    var jsonObj = attr as LitJsonObjectAttribute;
                    if (null != jsonObj && jsonObj.NoSelfType == true)
                    {
                        NoSelfType = true;
                    }
                }

                string keyname = (string)reader.Value;
                if (NoSelfType == false && keyname == "selfType")  //第一个字段为selftype 可以多态反射
                {
                    string classname = (string)ReadValue(typeof(string), reader);

                    Type classtype = FindTypeByName(classname);

                    if (null != classtype)
                    {
                        inst_type = classtype;

                        AddObjectMetadata(inst_type);
                        t_data = object_metadata[inst_type];
                    }

                    reader.Read();
                }

                if (inst_type.IsAbstract)
                {
                    while (true)
                    {
                        if (reader.Token == JsonToken.ObjectEnd)
                        {
                            instance = null;
                            break;
                        }

                        ReadSkip(reader);

                        reader.Read();
                    }
                }

                else if (inst_type == typeof(object))//如果期望的类型为object那么会自动转换成JsonData
                {
                    WrapperFactory factory = delegate { return(new JsonData()); };

                    instance = factory();

                    while (true)
                    {
                        if (reader.Token == JsonToken.ObjectEnd)
                        {
                            break;
                        }

                        string property = (string)reader.Value;

                        ((IDictionary)instance)[property] = ReadValue(factory, reader);

                        reader.Read();
                    }
                }
                else //按类的格式赋值
                {
                    if (reader.Token != JsonToken.ObjectEnd)
                    {
                        instance = Activator.CreateInstance(inst_type);
                    }
                    else
                    {
                        instance = null;
                    }

                    while (true)
                    {
                        if (reader.Token == JsonToken.ObjectEnd)
                        {
                            break;
                        }

                        string property = (string)reader.Value;

                        if (t_data.Properties.ContainsKey(property))
                        {
                            PropertyMetadata prop_data =
                                t_data.Properties[property];

                            if (prop_data.IsField)
                            {
                                ((FieldInfo)prop_data.Info).SetValue(
                                    instance, ReadValue(prop_data.Type, reader));
                            }
                            else
                            {
                                PropertyInfo p_info =
                                    (PropertyInfo)prop_data.Info;

                                if (p_info.CanWrite)
                                {
                                    p_info.SetValue(
                                        instance,
                                        ReadValue(prop_data.Type, reader),
                                        null);
                                }
                                else
                                {
                                    ReadValue(prop_data.Type, reader);
                                }
                            }
                        }
                        else
                        {
                            if (!t_data.IsDictionary)
                            {
                                if (!reader.SkipNonMembers)
                                {
                                    throw new JsonException(String.Format(
                                                                "The type {0} doesn't have the " +
                                                                "property '{1}'",
                                                                inst_type, property));
                                }
                                else
                                {
                                    ReadSkip(reader);
                                    reader.Read();
                                    continue;
                                }
                            }

                            ((IDictionary)instance).Add(
                                property, ReadValue(
                                    t_data.ElementType, reader));
                        }


                        reader.Read();
                    }
                }
            }

            return(instance);
        }
예제 #7
0
        static object ReadValue(Type inst_type, JsonData json)
        {
            if (json == null || json.JsonType == JsonType.None || (json.JsonType == JsonType.String && String.IsNullOrEmpty((string)json.Value) && !(inst_type == typeof(string))))
            {
                if (inst_type.GetTypeInfo().IsGenericType&& inst_type.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(Activator.CreateInstance(inst_type)); // empty nullable
                }
                if (!inst_type.GetTypeInfo().IsClass&& !inst_type.IsArray)
                {
                    throw new JsonException(String.Format("Can't assign null to an instance of type {0}", inst_type));
                }

                return(null);
            }

            object[] attrs;
            if ((attrs = inst_type.GetTypeInfo().GetCustomAttributes(typeof(JsonConverterAttribute), false).ToArray()) != null && attrs.Length == 1)
            {
                var jca = (JsonConverterAttribute)attrs[0];

                var jc = (IJsonConverter)Activator.CreateInstance(jca.Converter);

                object v_;
                if (jc.Deserialize(json, inst_type, out v_))
                {
                    return(v_);
                }
            }

            if (inst_type.GetTypeInfo().IsGenericType&& inst_type.GetGenericTypeDefinition() == typeof(Nullable <>)) // 'json' isn't null -> has a value
            {
                return(Activator.CreateInstance(inst_type, ReadValue(inst_type.GetGenericArguments()[0], json)));
            }

            var v = json.Value;

            switch (json.JsonType)
            {
            case JsonType.Double:
            case JsonType.Int:
            case JsonType.Long:
            case JsonType.String:
            case JsonType.Boolean:
                return(ConvertTo(inst_type, json.Value, json.NetType(inst_type)));

            case JsonType.Array:
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format("Type {0} can't act as an array", inst_type));
                }

                var inList = (IList <JsonData>)v;

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new List <object>();
                    elem_type = inst_type.GetElementType();
                }

                for (int i = 0; i < inList.Count; i++)
                {
                    list.Add(ReadValue(elem_type, inList[i]));
                }

                object inst;
                if (t_data.IsArray)
                {
                    int n = list.Count;
                    inst = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)inst).SetValue(list[i], i);
                    }
                }
                else
                {
                    inst = list;
                }

                return(inst);
            }

            case JsonType.Object:
            {
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                //throw new Exception("type is " + inst_type);
                var inst = Activator.CreateInstance(inst_type);

                var dict = (IDictionary <string, JsonData>)v;

                foreach (var kvp in dict)
                {
                    var prop  = kvp.Key;
                    var value = kvp.Value;

                    PropertyMetadata prop_data;
                    if (TryGetValueIgnCase(t_data.Properties, prop, out prop_data))
                    {
                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(inst, ReadValue(prop_data.Type, value));
                        }
                        else
                        {
                            var p_info = (PropertyInfo)prop_data.Info;

                            var    v_        = ReadValue(prop_data.Type, value);
                            object converted = null;

                            if ((attrs = p_info.GetCustomAttributes(typeof(JsonConverterAttribute), false).ToArray()) != null && attrs.Length == 1)
                            {
                                var jca = (JsonConverterAttribute)attrs[0];

                                var jc = (IJsonConverter)Activator.CreateInstance(jca.Converter);

                                jc.Deserialize(value, p_info.PropertyType, out converted);
                            }

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(inst, converted ?? ConvertTo(p_info.PropertyType, v_), null);
                            }
                            else
                            {
                                throw new MemberAccessException("Cannot set property '" + p_info + "' to '" + v_ + "'.");
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            throw new JsonException(String.Format("The type {0} doesn't have the property '{1}'", inst_type, prop));
                        }

                        ((IDictionary)inst).Add(prop, ReadValue(t_data.ElementType, value));
                    }
                }

                return(inst);
            }

            default:
                return(null);
            }
        }
예제 #8
0
        private static object ReadValue(Type inst_type, JsonReader reader)
        {
            reader.Read();

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            //ILRuntime doesn't support nullable valuetype
            Type underlying_type = inst_type; //Nullable.GetUnderlyingType(inst_type);
            Type value_type      = inst_type;

            if (reader.Token == JsonToken.Null)
            {
                if (inst_type.IsClass || underlying_type != null)
                {
                    return(null);
                }

                throw new JsonException(String.Format(
                                            "Can't assign null to an instance of type {0}",
                                            inst_type));
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type json_type = reader.Value.GetType();
                var  vt        = value_type is ILRuntime.Reflection.ILRuntimeWrapperType
                    ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR
                    : value_type;

                if (vt.IsAssignableFrom(json_type))
                {
                    return(reader.Value);
                }
                if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum)
                {
                    if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) ||
                        json_type == typeof(byte))
                    {
                        return(reader.Value);
                    }
                }

                // If there's a custom importer that fits, use it
                if (custom_importers_table.ContainsKey(json_type) &&
                    custom_importers_table[json_type].ContainsKey(
                        vt))
                {
                    ImporterFunc importer =
                        custom_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

                // Maybe there's a base importer that works
                if (base_importers_table.ContainsKey(json_type) &&
                    base_importers_table[json_type].ContainsKey(
                        vt))
                {
                    ImporterFunc importer =
                        base_importers_table[json_type][vt];

                    return(importer(reader.Value));
                }

                // Maybe it's an enum
                if (vt.IsEnum)
                {
                    return(Enum.ToObject(vt, reader.Value));
                }

                // Try using an implicit conversion operator
                MethodInfo conv_op = GetConvOp(vt, json_type);

                if (conv_op != null)
                {
                    return(conv_op.Invoke(null,
                                          new object[] { reader.Value }));
                }

                // No luck
                throw new JsonException(String.Format(
                                            "Can't assign value '{0}' (type {1}) to type {2}",
                                            reader.Value, json_type, inst_type));
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType
                        ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType
                        : elem_type;
                    item = rt.CheckCLRTypes(item);
                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(value_type);
                ObjectMetadata t_data = object_metadata[value_type];
                if (value_type is ILRuntime.Reflection.ILRuntimeType)
                {
                    instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate();
                }
                else
                {
                    if (value_type is ILRuntime.Reflection.ILRuntimeWrapperType)
                    {
                        value_type = ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).RealType;
                    }
                    instance = Activator.CreateInstance(value_type);
                }

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    string property = (string)reader.Value;

                    if (t_data.Properties.ContainsKey(property))
                    {
                        PropertyMetadata prop_data =
                            t_data.Properties[property];

                        if (prop_data.IsField)
                        {
                            var p_prop = ((FieldInfo)prop_data.Info);
                            var value  = ReadValue(prop_data.Type, reader);
                            p_prop.SetValue(instance, value);
                        }
                        else
                        {
                            var p_info = (PropertyInfo)prop_data.Info;
                            var value  = ReadValue(prop_data.Type, reader);
                            p_info.SetValue(instance, value);
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        var rt = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType
                            ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType
                            : t_data.ElementType;
                        ((IDictionary)instance).Add(
                            property, rt.CheckCLRTypes(ReadValue(
                                                           t_data.ElementType, reader)));
                    }
                }
            }

            return(instance);
        }
예제 #9
0
        static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            var data = new ObjectMetadata();

            if (Array.IndexOf(type.GetInterfaces(), typeof(IDictionary)) != -1)
            {
                data.IsDictionary = true;
            }

            data.Properties = new Dictionary <string, PropertyMetadata>();

            foreach (var p_info in type.GetProperties(BFlags))
            {
                if (p_info.Name == "Item" && (p_info.Attributes & PropertyAttributes.SpecialName) != 0)
                {
                    var parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    if (parameters[0].ParameterType == typeof(string))
                    {
                        data.ElementType = p_info.PropertyType;
                    }

                    continue;
                }

                var p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);

                foreach (var o in p_info.GetCustomAttributes(typeof(JsonPropertyNameAttribute), true))
                {
                    var jpn = (JsonPropertyNameAttribute)o;

                    if (!data.Properties.ContainsKey(jpn.Name))
                    {
                        data.Properties.Add(jpn.Name, p_data);
                    }
                }
            }

            foreach (var f_info in type.GetFields(BFlags))
            {
                var p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);

                foreach (var o in f_info.GetCustomAttributes(typeof(JsonPropertyNameAttribute), true))
                {
                    var jpn = (JsonPropertyNameAttribute)o;

                    if (!data.Properties.ContainsKey(jpn.Name))
                    {
                        data.Properties.Add(jpn.Name, p_data);
                    }
                }
            }

            lock (object_metadata_lock)
            {
                try
                {
                    object_metadata.Add(type, data);
                }
                catch (ArgumentException)
                {
                    return;
                }
            }
        }
예제 #10
0
        private static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            ObjectMetadata data = new ObjectMetadata();

            if (HasInterface(type, "System.Collections.IDictionary"))
            {
                data.IsDictionary = true;
            }

            data.Properties = new Dictionary <string, PropertyMetadata> ();

            foreach (PropertyInfo p_info in GetPublicInstanceProperties(type))
            {
                if (p_info.Name == "Item")
                {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    if (parameters[0].ParameterType == typeof(string))
                    {
                        data.ElementType = p_info.PropertyType;
                    }

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);
            }

            foreach (FieldInfo f_info in
#if NETFX_CORE
                     type.GetRuntimeFields()
#else
                     type.GetFields()
#endif
                     )
            {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock) {
                try {
                    object_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #11
0
        private static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
            {
                data.IsDictionary = true;
            }

            data.Properties = new Dictionary <string, PropertyMetadata>();

            //this do for :  int x{get;private set}   set is null~
            var flag = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;
            List <PropertyInfo> props = new List <PropertyInfo>();
            Type startType            = type;

            while (startType != null)
            {
                props.AddRange(startType.GetProperties(flag));
                startType = startType.BaseType;
            }


            foreach (PropertyInfo p_info in props)
            {
                if (p_info.Name == "Item")
                {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    if (parameters[0].ParameterType == typeof(string))
                    {
                        if (type is ILRuntime.Reflection.ILRuntimeWrapperType)
                        {
                            data.ElementType = ((ILRuntime.Reflection.ILRuntimeWrapperType)type).CLRType
                                               .GenericArguments[1].Value.ReflectionType;
                        }
                        else
                        {
                            data.ElementType = p_info.PropertyType;
                        }
                    }

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);
            }

            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
                                        BindingFlags.NonPublic);

            foreach (FieldInfo f_info in fields)
            {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock)
            {
                try
                {
                    object_metadata.Add(type, data);
                }
                catch (ArgumentException)
                {
                    return;
                }
            }
        }
예제 #12
0
        private static void WriteValue(object obj, JsonWriter writer, bool privateWriter, int depth)
        {
            if (depth > maxNestingDepth)
            {
                throw new JsonException(string.Format("Max allowed object depth reached while trying to export from type {0}", obj.GetType()));
            }
            if (obj == null)
            {
                writer.Write(null);
                return;
            }
            if (obj is IJsonWrapper)
            {
                if (privateWriter)
                {
                    writer.TextWriter.Write(((IJsonWrapper)obj).ToJson());
                }
                else
                {
                    ((IJsonWrapper)obj).ToJson(writer);
                }
                return;
            }
            if (obj is string)
            {
                writer.Write((string)obj);
                return;
            }
            if (obj is double)
            {
                writer.Write((double)obj);
                return;
            }
            if (obj is long)
            {
                writer.Write((long)obj);
                return;
            }
            if (obj is bool)
            {
                writer.Write((bool)obj);
                return;
            }
            if (obj is Array)
            {
                writer.WriteArrayStart();
                Array arr      = (Array)obj;
                Type  elemType = arr.GetType().GetElementType();
                foreach (object elem in arr)
                {
                    // if the collection contains polymorphic elements, we need to include type information for deserialization
                    if (writer.TypeHinting && elem != null & elem.GetType() != elemType)
                    {
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(elem.GetType().FullName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(elem, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(elem, writer, privateWriter, depth + 1);
                    }
                }
                writer.WriteArrayEnd();
                return;
            }
            if (obj is IList)
            {
                writer.WriteArrayStart();
                IList list = (IList)obj;
                // collection might be non-generic type like Arraylist
                Type elemType = typeof(object);
                if (list.GetType().GetGenericArguments().Length > 0)
                {
                    // collection is a generic type like List<T>
                    elemType = list.GetType().GetGenericArguments()[0];
                }
                foreach (object elem in list)
                {
                    // if the collection contains polymorphic elements, we need to include type information for deserialization
                    if (writer.TypeHinting && elem != null && elem.GetType() != elemType)
                    {
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(elem.GetType().AssemblyQualifiedName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(elem, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(elem, writer, privateWriter, depth + 1);
                    }
                }
                writer.WriteArrayEnd();
                return;
            }
            if (obj is IDictionary)
            {
                writer.WriteObjectStart();
                IDictionary dict = (IDictionary)obj;
                // collection might be non-generic type like Hashtable
                Type elemType = typeof(object);
                if (dict.GetType().GetGenericArguments().Length > 1)
                {
                    // collection is a generic type like Dictionary<T, V>
                    elemType = dict.GetType().GetGenericArguments()[1];
                }
                foreach (DictionaryEntry entry in dict)
                {
                    writer.WritePropertyName((string)entry.Key);
                    // if the collection contains polymorphic elements, we need to include type information for deserialization
                    if (writer.TypeHinting && entry.Value != null && entry.Value.GetType() != elemType)
                    {
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(entry.Value.GetType().AssemblyQualifiedName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(entry.Value, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(entry.Value, writer, privateWriter, depth + 1);
                    }
                }
                writer.WriteObjectEnd();
                return;
            }
            Type objType = obj.GetType();
            // Try a base or custom importer if one exists
            ExporterFunc exporter = GetExporter(objType);

            if (exporter != null)
            {
                exporter(obj, writer);
                return;
            }
            // Last option, let's see if it's an enum
            if (obj is Enum)
            {
                Type enumType = Enum.GetUnderlyingType(objType);
                if (enumType == typeof(long))
                {
                    writer.Write((long)obj);
                }
                else
                {
                    ExporterFunc enumConverter = GetExporter(enumType);
                    if (enumConverter != null)
                    {
                        enumConverter(obj, writer);
                    }
                }
                return;
            }
            // Okay, it looks like the input should be exported as an object
            ObjectMetadata tdata = AddObjectMetadata(objType);

            writer.WriteObjectStart();
            foreach (string property in tdata.Properties.Keys)
            {
                PropertyMetadata pdata = tdata.Properties[property];
                // Don't serialize soft aliases (which get added to ObjectMetadata.Properties twice).
                if (pdata.Alias != null && property != pdata.Info.Name && tdata.Properties.ContainsKey(pdata.Info.Name))
                {
                    continue;
                }
                // Don't serialize a field or property with the JsonIgnore attribute with serialization usage
                if ((pdata.Ignore & JsonIgnoreWhen.Serializing) > 0)
                {
                    continue;
                }
                if (pdata.IsField)
                {
                    FieldInfo info = (FieldInfo)pdata.Info;
                    if (pdata.Alias != null)
                    {
                        writer.WritePropertyName(pdata.Alias);
                    }
                    else
                    {
                        writer.WritePropertyName(info.Name);
                    }
                    object value = info.GetValue(obj);
                    if (writer.TypeHinting && value != null && info.FieldType != value.GetType())
                    {
                        // the object stored in the field might be a different type that what was declared, need type hinting
                        writer.WriteObjectStart();
                        writer.WritePropertyName(writer.HintTypeName);
                        writer.Write(value.GetType().AssemblyQualifiedName);
                        writer.WritePropertyName(writer.HintValueName);
                        WriteValue(value, writer, privateWriter, depth + 1);
                        writer.WriteObjectEnd();
                    }
                    else
                    {
                        WriteValue(value, writer, privateWriter, depth + 1);
                    }
                }
                else
                {
                    PropertyInfo info = (PropertyInfo)pdata.Info;
                    if (info.CanRead)
                    {
                        if (pdata.Alias != null)
                        {
                            writer.WritePropertyName(pdata.Alias);
                        }
                        else
                        {
                            writer.WritePropertyName(info.Name);
                        }
                        object value = info.GetValue(obj, null);
                        if (writer.TypeHinting && value != null && info.PropertyType != value.GetType())
                        {
                            // the object stored in the property might be a different type that what was declared, need type hinting
                            writer.WriteObjectStart();
                            writer.WritePropertyName(writer.HintTypeName);
                            writer.Write(value.GetType().AssemblyQualifiedName);
                            writer.WritePropertyName(writer.HintValueName);
                            WriteValue(value, writer, privateWriter, depth + 1);
                            writer.WriteObjectEnd();
                        }
                        else
                        {
                            WriteValue(value, writer, privateWriter, depth + 1);
                        }
                    }
                }
            }
            writer.WriteObjectEnd();
        }
예제 #13
0
        private static object ReadValue(Type instType, JsonReader reader)
        {
            reader.Read();
            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }
            Type underlyingType = Nullable.GetUnderlyingType(instType);
            Type valueType      = underlyingType ?? instType;

            if (reader.Token == JsonToken.Null)
            {
                        #if JSON_WINRT || (UNITY_METRO && !UNITY_EDITOR)
                /* IsClass is made a getter here as a comparability
                 * patch for WinRT build targets, see Platform.cs */
                if (instType.IsClass() || underlyingType != null)
                {
                        #else
                if (instType.IsClass || underlyingType != null)
                {
                        #endif
                    return(null);
                }
                throw new JsonException(string.Format("Can't assign null to an instance of type {0}", instType));
            }
            if (reader.Token == JsonToken.Real ||
                reader.Token == JsonToken.Natural ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                Type jsonType = reader.Value.GetType();
                if (valueType.IsAssignableFrom(jsonType))
                {
                    return(reader.Value);
                }
                // Try to find a custom or base importer
                ImporterFunc importer = GetImporter(jsonType, valueType);
                if (importer != null)
                {
                    return(importer(reader.Value));
                }
                // Maybe it's an enum
                        #if JSON_WINRT || (UNITY_METRO && !UNITY_EDITOR)
                /* IsClass is made a getter here as a comparability
                 * patch for WinRT build targets, see Platform.cs */
                if (valueType.IsEnum())
                {
                        #else
                if (valueType.IsEnum)
                {
                        #endif
                    return(Enum.ToObject(valueType, reader.Value));
                }
                // Try using an implicit conversion operator
                MethodInfo convOp = GetConvOp(valueType, jsonType);
                if (convOp != null)
                {
                    return(convOp.Invoke(null, new object[] { reader.Value }));
                }
                // No luck
                throw new JsonException(string.Format("Can't assign value '{0}' (type {1}) to type {2}", reader.Value, jsonType, instType));
            }
            object instance = null;
            if (reader.Token == JsonToken.ArrayStart)
            {
                // If there's a custom importer that fits, use it
                ImporterFunc importer = GetImporter(typeof(JsonData), instType);
                if (importer != null)
                {
                    instType = typeof(JsonData);
                }
                AddArrayMetadata(instType);
                ArrayMetadata tdata = arrayMetadata[instType];
                if (!tdata.IsArray && !tdata.IsList)
                {
                    throw new JsonException(string.Format("Type {0} can't act as an array", instType));
                }
                IList list;
                Type  elemType;
                if (!tdata.IsArray)
                {
                    list     = (IList)CreateInstance(instType);
                    elemType = tdata.ElementType;
                }
                else
                {
                    //list = new ArrayList();
                    list     = new List <object>();
                    elemType = instType.GetElementType();
                }
                while (true)
                {
                    object item = ReadValue(elemType, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }
                    list.Add(item);
                }
                if (tdata.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elemType, n);
                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
                if (importer != null)
                {
                    instance = importer(instance);
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                bool   done     = false;
                string property = null;
                reader.Read();
                if (reader.Token == JsonToken.ObjectEnd)
                {
                    done = true;
                }
                else
                {
                    property = (string)reader.Value;
                    if (reader.TypeHinting && property == reader.HintTypeName)
                    {
                        reader.Read();
                        string typeName = (string)reader.Value;
                        reader.Read();
                        if ((string)reader.Value == reader.HintValueName)
                        {
                            valueType = Type.GetType(typeName);
                            object value = ReadValue(valueType, reader);
                            reader.Read();
                            if (reader.Token != JsonToken.ObjectEnd)
                            {
                                throw new JsonException(string.Format("Invalid type hinting object, has too many properties: {0}...", reader.Token));
                            }
                            return(value);
                        }
                        else
                        {
                            throw new JsonException(string.Format("Expected \"{0}\" property for type hinting but instead got \"{1}\"", reader.HintValueName, reader.Value));
                        }
                    }
                }
                // If there's a custom importer that fits, use to create a JsonData type instead.
                // Once the object is deserialzied, it will be invoked to create the actual converted object.
                ImporterFunc importer = GetImporter(typeof(JsonData), valueType);
                if (importer != null)
                {
                    valueType = typeof(JsonData);
                }
                ObjectMetadata tdata = AddObjectMetadata(valueType);
                instance = CreateInstance(valueType);
                bool firstRun = true;
                while (!done)
                {
                    if (firstRun)
                    {
                        firstRun = false;
                    }
                    else
                    {
                        reader.Read();
                        if (reader.Token == JsonToken.ObjectEnd)
                        {
                            break;
                        }
                        property = (string)reader.Value;
                    }
                    PropertyMetadata pdata;
                    if (tdata.Properties.TryGetValue(property, out pdata))
                    {
                        // Don't deserialize a field or property that has a JsonIgnore attribute with deserialization usage.
                        if ((pdata.Ignore & JsonIgnoreWhen.Deserializing) > 0)
                        {
                            ReadSkip(reader);
                            continue;
                        }
                        if (pdata.IsField)
                        {
                            ((FieldInfo)pdata.Info).SetValue(instance, ReadValue(pdata.Type, reader));
                        }
                        else
                        {
                            PropertyInfo pinfo = (PropertyInfo)pdata.Info;
                            if (pinfo.CanWrite)
                            {
                                pinfo.SetValue(instance, ReadValue(pdata.Type, reader), null);
                            }
                            else
                            {
                                ReadValue(pdata.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!tdata.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(string.Format("The type {0} doesn't have the property '{1}'", instType, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }
                        ((IDictionary)instance).Add(property, ReadValue(tdata.ElementType, reader));
                    }
                }
                if (importer != null)
                {
                    instance = importer(instance);
                }
            }
            return(instance);
        }
예제 #14
0
        private static ObjectMetadata AddObjectMetadata(Type type)
        {
            if (objectMetadata.ContainsKey(type))
            {
                return(objectMetadata[type]);
            }
            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
            {
                data.IsDictionary = true;
            }
            data.Properties = new Dictionary <string, PropertyMetadata>();
            HashSet <string> ignoredMembers = new HashSet <string>();

            object[] memberAttrs = type.GetCustomAttributes(typeof(JsonIgnoreMember), true);
            foreach (JsonIgnoreMember memberAttr in memberAttrs)
            {
                ignoredMembers.UnionWith(memberAttr.Members);
            }
            // Get all kinds of declared properties
            BindingFlags pflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

            foreach (PropertyInfo pinfo in type.GetProperties(pflags))
            {
                if (pinfo.Name == "Item")
                {
                    ParameterInfo[] parameters = pinfo.GetIndexParameters();
                    if (parameters.Length != 1)
                    {
                        continue;
                    }
                    if (parameters[0].ParameterType == typeof(string))
                    {
                        data.ElementType = pinfo.PropertyType;
                    }
                    continue;
                }
                // Include properties automatically that have at least one public accessor
                bool autoInclude =
                    (pinfo.GetGetMethod() != null && pinfo.GetGetMethod().IsPublic) ||
                    (pinfo.GetSetMethod() != null && pinfo.GetSetMethod().IsPublic);
                // If neither accessor is public and we don't have a [JsonInclude] attribute, skip it
                if (!autoInclude && pinfo.GetCustomAttributes(typeof(JsonInclude), true).Count() == 0)
                {
                    continue;
                }
                PropertyMetadata pdata = new PropertyMetadata();
                pdata.Info = pinfo;
                pdata.Type = pinfo.PropertyType;
                object[] ignoreAttrs = pinfo.GetCustomAttributes(typeof(JsonIgnore), true).ToArray();
                if (ignoreAttrs.Length > 0)
                {
                    pdata.Ignore = ((JsonIgnore)ignoreAttrs[0]).Usage;
                }
                else if (ignoredMembers.Contains(pinfo.Name))
                {
                    pdata.Ignore = JsonIgnoreWhen.Serializing | JsonIgnoreWhen.Deserializing;
                }
                object[] aliasAttrs = pinfo.GetCustomAttributes(typeof(JsonAlias), true).ToArray();
                if (aliasAttrs.Length > 0)
                {
                    JsonAlias aliasAttr = (JsonAlias)aliasAttrs[0];
                    if (aliasAttr.Alias == pinfo.Name)
                    {
                        throw new JsonException(string.Format("Alias name '{0}' must be different from the property it represents for type '{1}'", pinfo.Name, type));
                    }
                    if (data.Properties.ContainsKey(aliasAttr.Alias))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the property or alias name '{1}'", type, aliasAttr.Alias));
                    }
                    pdata.Alias = aliasAttr.Alias;
                    if (aliasAttr.AcceptOriginal)
                    {
                        data.Properties.Add(pinfo.Name, pdata);
                    }
                }
                if (pdata.Alias != null)
                {
                    data.Properties.Add(pdata.Alias, pdata);
                }
                else
                {
                    if (data.Properties.ContainsKey(pinfo.Name))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the property or alias name '{1}'", type, pinfo.Name));
                    }
                    data.Properties.Add(pinfo.Name, pdata);
                }
            }
            // Get all kinds of declared fields
            BindingFlags fflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

            foreach (FieldInfo finfo in type.GetFields(fflags))
            {
                // If the field isn't public and doesn't have an [Include] attribute, skip it
                if (!finfo.IsPublic && finfo.GetCustomAttributes(typeof(JsonInclude), true).Count() == 0)
                {
                    continue;
                }
                PropertyMetadata pdata = new PropertyMetadata();
                pdata.Info    = finfo;
                pdata.IsField = true;
                pdata.Type    = finfo.FieldType;
                object[] ignoreAttrs = finfo.GetCustomAttributes(typeof(JsonIgnore), true).ToArray();
                if (ignoreAttrs.Length > 0)
                {
                    pdata.Ignore = ((JsonIgnore)ignoreAttrs[0]).Usage;
                }
                else if (ignoredMembers.Contains(finfo.Name))
                {
                    pdata.Ignore = JsonIgnoreWhen.Serializing | JsonIgnoreWhen.Deserializing;
                }
                object[] aliasAttrs = finfo.GetCustomAttributes(typeof(JsonAlias), true).ToArray();
                if (aliasAttrs.Length > 0)
                {
                    JsonAlias aliasAttr = (JsonAlias)aliasAttrs[0];
                    if (aliasAttr.Alias == finfo.Name)
                    {
                        throw new JsonException(string.Format("Alias name '{0}' must be different from the field it represents for type '{1}'", finfo.Name, type));
                    }
                    if (data.Properties.ContainsKey(aliasAttr.Alias))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the field or alias name '{1}'", type, aliasAttr.Alias));
                    }
                    pdata.Alias = aliasAttr.Alias;
                    if (aliasAttr.AcceptOriginal)
                    {
                        data.Properties.Add(finfo.Name, pdata);
                    }
                }
                if (pdata.Alias != null)
                {
                    data.Properties.Add(pdata.Alias, pdata);
                }
                else
                {
                    if (data.Properties.ContainsKey(finfo.Name))
                    {
                        throw new JsonException(string.Format("'{0}' already contains the field or alias name '{1}'", type, finfo.Name));
                    }
                    data.Properties.Add(finfo.Name, pdata);
                }
            }
            objectMetadata.Add(type, data);
            return(data);
        }
예제 #15
0
        private static void AddObjectMetadata(Type type)
        {
            if (object_metadata.ContainsKey(type))
            {
                return;
            }

            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
            {
                data.IsDictionary = true;
            }

            data.Properties = new Dictionary <string, PropertyMetadata> ();
            foreach (PropertyInfo p_info in type.GetProperties())
            {
                if (Attribute.IsDefined(p_info, typeof(JsonIgnoreAttribute), true))
                {
                    continue;
                }
                if (p_info.Name == "Item")
                {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    if (parameters[0].ParameterType == typeof(string))
                    {
                        if (type is ILRuntime.Reflection.ILRuntimeWrapperType)
                        {
                            data.ElementType = ((ILRuntime.Reflection.ILRuntimeWrapperType)type).CLRType.GenericArguments[1].Value.ReflectionType;
                        }
                        else
                        {
                            data.ElementType = p_info.PropertyType;
                        }
                    }

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);
            }

            foreach (FieldInfo f_info in type.GetFields())
            {
                if (Attribute.IsDefined(f_info, typeof(JsonIgnoreAttribute), true))
                {
                    continue;
                }
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info    = f_info;
                p_data.IsField = true;
                p_data.Type    = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock) {
                try {
                    object_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #16
0
        static object ReadValue(Type inst_type, JsonReader reader, bool readBegin = true)
        {
            if (readBegin)
            {
                reader.Read();
            }

            if (reader.Token == JsonToken.ArrayEnd)
            {
                return(null);
            }

            if (reader.Token == JsonToken.Null || (reader.Token == JsonToken.String && String.IsNullOrEmpty((string)reader.Value) && !(inst_type == typeof(string))))
            {
                if (!inst_type.GetTypeInfo().IsClass&& !inst_type.IsArray)
                {
                    throw new JsonException(String.Format("Can't assign null to an instance of type {0}", inst_type));
                }

                return(null);
            }

            if (inst_type.GetTypeInfo().IsGenericType&& inst_type.GetGenericTypeDefinition() == typeof(Nullable <>)) // isn't null -> has a value
            {
                return(Activator.CreateInstance(inst_type, ReadValue(inst_type.GetGenericArguments()[0], reader, false)));
            }

            if (reader.Token == JsonToken.Double ||
                reader.Token == JsonToken.Int ||
                reader.Token == JsonToken.Long ||
                reader.Token == JsonToken.String ||
                reader.Token == JsonToken.Boolean)
            {
                return(ConvertTo(inst_type, reader.Value, reader.Value.GetType()));
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format("Type {0} can't act as an array", inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new List <object>();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }

                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_type);

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    var property = (string)reader.Value;

                    PropertyMetadata prop_data;
                    if (TryGetValueIgnCase(t_data.Properties, property, out prop_data))
                    {
                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(instance, ReadValue(prop_data.Type, reader));
                        }
                        else
                        {
                            var p_info = (PropertyInfo)prop_data.Info;

                            var v = ReadValue(prop_data.Type, reader);

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(instance, ConvertTo(p_info.PropertyType, v), null);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format("The type {0} doesn't have the property '{1}'", inst_type, property));
                            }

                            ReadSkip(reader);
                            continue;
                        }

                        ((IDictionary)instance).Add(property, ReadValue(t_data.ElementType, reader));
                    }
                }
            }

            return(instance);
        }
예제 #17
0
        private static void AddObjectMetadata (Type type)
        {
        	if (object_metadata.Contains(type))
                return;

            ObjectMetadata data = new ObjectMetadata();

            if (type.GetInterface("System.Collections.IDictionary") != null)
                data.IsDictionary = true;

            data.Properties = new Hashtable();

            foreach (PropertyInfo p_info in type.GetProperties ()) {
                if (p_info.Name == "Item") {
                    ParameterInfo[] parameters = p_info.GetIndexParameters();

                    if (parameters.Length != 1)
                        continue;

                    if (parameters[0].ParameterType == typeof (string))
                        data.ElementType = p_info.PropertyType;

                    continue;
                }

                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = p_info;
                p_data.Type = p_info.PropertyType;

                data.Properties.Add(p_info.Name, p_data);
            }

            foreach (FieldInfo f_info in type.GetFields()) {
                PropertyMetadata p_data = new PropertyMetadata();
                p_data.Info = f_info;
                p_data.IsField = true;
                p_data.Type = f_info.FieldType;

                data.Properties.Add(f_info.Name, p_data);
            }

            lock (object_metadata_lock) {
                try {
                    object_metadata.Add(type, data);
                } catch (ArgumentException) {
                    return;
                }
            }
        }
예제 #18
0
        public static T ReadValueEx <T>(JsonReader reader)
        {
            Type inst_type = typeof(T);

            while (reader.Read())
            {
                if (reader.Token == JsonToken.ArrayEnd || reader.Token == JsonToken.Null)
                {
                    return(default(T));
                }
                if (reader.Token == JsonToken.ArrayStart || reader.Token == JsonToken.ObjectStart)
                {
                    break;
                }
            }

            object instance = null;

            if (reader.Token == JsonToken.ArrayStart)
            {
                AddArrayMetadata(inst_type);
                ArrayMetadata t_data = array_metadata[inst_type];

                if (!t_data.IsArray && !t_data.IsList)
                {
                    throw new JsonException(String.Format(
                                                "Type {0} can't act as an array",
                                                inst_type));
                }

                IList list;
                Type  elem_type;

                if (!t_data.IsArray)
                {
                    list      = (IList)Activator.CreateInstance(inst_type);
                    elem_type = t_data.ElementType;
                }
                else
                {
                    list      = new ArrayList();
                    elem_type = inst_type.GetElementType();
                }

                while (true)
                {
                    object item = ReadValue(elem_type, reader);
                    if (item == null && reader.Token == JsonToken.ArrayEnd)
                    {
                        break;
                    }

                    list.Add(item);
                }

                if (t_data.IsArray)
                {
                    int n = list.Count;
                    instance = Array.CreateInstance(elem_type, n);

                    for (int i = 0; i < n; i++)
                    {
                        ((Array)instance).SetValue(list[i], i);
                    }
                }
                else
                {
                    instance = list;
                }
            }
            else if (reader.Token == JsonToken.ObjectStart)
            {
                AddObjectMetadata(inst_type);
                ObjectMetadata t_data = object_metadata[inst_type];

                instance = Activator.CreateInstance(inst_type);

                while (true)
                {
                    reader.Read();

                    if (reader.Token == JsonToken.ObjectEnd)
                    {
                        break;
                    }

                    string property = (string)reader.Value;

                    if (t_data.Properties.ContainsKey(property))
                    {
                        PropertyMetadata prop_data =
                            t_data.Properties[property];

                        if (prop_data.IsField)
                        {
                            ((FieldInfo)prop_data.Info).SetValue(
                                instance, ReadValue(prop_data.Type, reader));
                        }
                        else
                        {
                            PropertyInfo p_info =
                                (PropertyInfo)prop_data.Info;

                            if (p_info.CanWrite)
                            {
                                p_info.SetValue(
                                    instance,
                                    ReadValue(prop_data.Type, reader),
                                    null);
                            }
                            else
                            {
                                ReadValue(prop_data.Type, reader);
                            }
                        }
                    }
                    else
                    {
                        if (!t_data.IsDictionary)
                        {
                            if (!reader.SkipNonMembers)
                            {
                                throw new JsonException(String.Format(
                                                            "The type {0} doesn't have the " +
                                                            "property '{1}'",
                                                            inst_type, property));
                            }
                            else
                            {
                                ReadSkip(reader);
                                continue;
                            }
                        }

                        ((IDictionary)instance).Add(
                            property, ReadValue(
                                t_data.ElementType, reader));
                    }
                }
            }
            if (instance == null)
            {
                return(default(T));
            }
            return((T)instance);
        }