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); }
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); }
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; } } }
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; } } }
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); }
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); }
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); } }
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); }
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; } } }
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; } } }
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; } } }
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(); }
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); }
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); }
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; } } }
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); }
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; } } }
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); }