private static object ReadValue(Type inst_type, JsonReader reader) { reader.Read(); ITypeInfo typeInfo = TypeFactory.GetTypeInfo(inst_type); if (reader.Token == JsonToken.ArrayEnd) { return(null); } Type underlyingType = Nullable.GetUnderlyingType(inst_type); Type type = underlyingType ?? inst_type; if (reader.Token == JsonToken.Null) { if (typeInfo.IsClass || underlyingType != null) { return(null); } throw new JsonException($"Can't assign null to an instance of type {inst_type}"); } if (reader.Token == JsonToken.Double || reader.Token == JsonToken.Int || reader.Token == JsonToken.UInt || reader.Token == JsonToken.Long || reader.Token == JsonToken.ULong || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean) { Type type2 = reader.Value.GetType(); ITypeInfo typeInfo2 = TypeFactory.GetTypeInfo(type2); if (typeInfo.IsAssignableFrom(typeInfo2)) { return(reader.Value); } if (custom_importers_table.ContainsKey(type2) && custom_importers_table[type2].ContainsKey(type)) { return(custom_importers_table[type2][type](reader.Value)); } if (base_importers_table.ContainsKey(type2) && base_importers_table[type2].ContainsKey(type)) { return(base_importers_table[type2][type](reader.Value)); } if (typeInfo.IsEnum) { return(Enum.ToObject(type, reader.Value)); } MethodInfo convOp = GetConvOp(type, type2); if (convOp != null) { return(convOp.Invoke(null, new object[1] { reader.Value })); } throw new JsonException($"Can't assign value '{reader.Value}' (type {type2}) to type {inst_type}"); } object obj = null; if (reader.Token == JsonToken.ArrayStart) { AddArrayMetadata(inst_type); ArrayMetadata arrayMetadata = array_metadata[inst_type]; if (!arrayMetadata.IsArray && !arrayMetadata.IsList) { throw new JsonException($"Type {inst_type} can't act as an array"); } IList list; Type elementType; if (!arrayMetadata.IsArray) { list = (IList)Activator.CreateInstance(inst_type); elementType = arrayMetadata.ElementType; } else { list = new List <object>(); elementType = inst_type.GetElementType(); } while (true) { object value = ReadValue(elementType, reader); if (reader.Token == JsonToken.ArrayEnd) { break; } list.Add(value); } if (arrayMetadata.IsArray) { int count = list.Count; obj = Array.CreateInstance(elementType, count); for (int i = 0; i < count; i++) { ((Array)obj).SetValue(list[i], i); } } else { obj = list; } } else if (reader.Token == JsonToken.ObjectStart) { AddObjectMetadata(type); ObjectMetadata objectMetadata = object_metadata[type]; obj = Activator.CreateInstance(type); while (true) { reader.Read(); if (reader.Token == JsonToken.ObjectEnd) { break; } string text = (string)reader.Value; if (objectMetadata.Properties.ContainsKey(text)) { PropertyMetadata propertyMetadata = objectMetadata.Properties[text]; if (propertyMetadata.IsField) { ((FieldInfo)propertyMetadata.Info).SetValue(obj, ReadValue(propertyMetadata.Type, reader)); } else { PropertyInfo propertyInfo = (PropertyInfo)propertyMetadata.Info; if (propertyInfo.CanWrite) { propertyInfo.SetValue(obj, ReadValue(propertyMetadata.Type, reader), null); } else { ReadValue(propertyMetadata.Type, reader); } } } else { if (!objectMetadata.IsDictionary) { throw new JsonException($"The type {inst_type} doesn't have the property '{text}'"); } ((IDictionary)obj).Add(text, ReadValue(objectMetadata.ElementType, reader)); } } } return(obj); }
private static object ReadValue(Type inst_type, JsonReader reader) { reader.Read(); var inst_typeInfo = TypeFactory.GetTypeInfo(inst_type); if (reader.Token == JsonToken.ArrayEnd) { return(null); } //support for nullable types Type underlying_type = Nullable.GetUnderlyingType(inst_type); Type value_type = underlying_type ?? inst_type; if (reader.Token == JsonToken.Null) { if (inst_typeInfo.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.UInt || reader.Token == JsonToken.Long || reader.Token == JsonToken.ULong || reader.Token == JsonToken.String || reader.Token == JsonToken.Boolean) { Type json_type = reader.Value.GetType(); var json_typeInfo = TypeFactory.GetTypeInfo(json_type); if (inst_typeInfo.IsAssignableFrom(json_typeInfo)) { 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 (inst_typeInfo.IsEnum) { return(Enum.ToObject(value_type, reader.Value)); } // 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 List <object> (); elem_type = inst_type.GetElementType(); } while (true) { object item = ReadValue(elem_type, reader); 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; } } 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) { throw new JsonException(String.Format( "The type {0} doesn't have the " + "property '{1}'", inst_type, property)); } ((IDictionary)instance).Add( property, ReadValue( t_data.ElementType, reader)); } } } return(instance); }