private static void AddInheritMetadata(Type type) { if (inherit_metadata.ContainsKey(type)) { return; } InheritMetadata m = new InheritMetadata(); object[] attrs = type.GetCustomAttributes(typeof(JsonCanInheritAttribute), true); m.IsInherit = attrs != null && attrs.Length > 0; lock (inherit_metadata_lock) { try { inherit_metadata.Add(type, m); } catch (ArgumentException) { return; } } }
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 (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(); if (value_type.IsAssignableFrom(json_type)) { ////调试 //if(reader.Token == JsonToken.String) //{ // string s = (string)reader.Value; // if(s == "flyer_xuanfengzhan") // { // Debuger.LogError("调试"); // } // return s; //} //else return(reader.Value); } switch (reader.Token) { case JsonToken.Int: if (value_type == typeof(long)) { return((long)(int)reader.Value); } if (value_type == typeof(Property)) { return(new Property((int)reader.Value)); } break; case JsonToken.Long: if (value_type == typeof(int)) { return((int)(long)reader.Value); } if (value_type == typeof(Property)) { return(new Property((long)reader.Value)); } break; case JsonToken.String: if (value_type == typeof(Property)) { return(new Property((string)reader.Value)); } break; case JsonToken.Double: if (value_type == typeof(float)) { return((float)(double)reader.Value); } if (value_type == typeof(long)) { return((long)(double)reader.Value); } if (value_type == typeof(int)) { return((int)(double)reader.Value); } if (value_type == typeof(Property)) { return(new Property((float)(double)reader.Value)); } break; } // 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 (value_type.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 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) { AddInheritMetadata(value_type); InheritMetadata i_data = inherit_metadata[value_type]; //如果允许多态的话要判断当前的类型 if (i_data.IsInherit) { reader.Read(); string property = (string)reader.Value; if (property == "__type") { string trueTypeName = (string)ReadValue(typeof(string), reader); Type trueType; if (!typeDict.TryGetValue(trueTypeName, out trueType)) { trueType = Type.GetType(trueTypeName); typeDict[trueTypeName] = trueType; } if (trueType != null) { value_type = trueType; } else { Debuger.LogError("找不到类名对应的类型:{0}", trueTypeName); } } else { Debuger.LogError("逻辑错误,可能是老版本"); } } instance = Activator.CreateInstance(value_type); AddObjectMetadata(value_type); ObjectMetadata t_data = object_metadata[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.IsList) { IList l = (IList)instance; int idx; if (!int.TryParse(property, out idx)) { Debuger.LogError("json尝试将键值对转为数组失败,类型:{0},转换失败的key:{1}", value_type.Name, property); ReadSkip(reader); continue; } //如果不够,那么先补上 for (int i = l.Count; i <= idx; ++i) { if (t_data.ElementType.IsValueType) { l.Add(Activator.CreateInstance(value_type)); } else { l.Add(null); } } //设置值 l[idx] = ReadValue(t_data.ElementType, reader); } else if (t_data.IsDictionary) { if (t_data.KeyType == typeof(string)) { ((IDictionary)instance).Add(property, ReadValue(t_data.ElementType, reader)); } else { object k; if (!StringUtil.TryParse(property, t_data.KeyType, out k)) { Debuger.LogError("json尝试将键值对转换成:{0}时失败,转换失败的key:{1}", value_type.Name, property); ReadSkip(reader); continue; } ((IDictionary)instance).Add(k, ReadValue(t_data.ElementType, reader)); } } else if (!reader.SkipNonMembers) { throw new JsonException(String.Format( "The type {0} doesn't have the " + "property '{1}'", inst_type, property)); } else { ReadSkip(reader); continue; } } } return(instance); }
private static void WriteValue(object obj, JsonWriter writer, bool writer_is_private, int depth) { if (depth > max_nesting_depth) { 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 (writer_is_private) { writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); } else { ((IJsonWrapper)obj).ToJson(writer); } return; } if (obj is Property) { ((Property)obj).ToJson(writer); return; } if (obj is String) { writer.Write((string)obj); return; } if (obj is float) { writer.Write((double)(float)obj); return; } if (obj is Double) { writer.Write((double)obj); return; } if (obj is Int32) { writer.Write((int)obj); return; } if (obj is Boolean) { writer.Write((bool)obj); return; } if (obj is Int64) { writer.Write((long)obj); return; } if (obj is Array) { writer.WriteArrayStart(); foreach (object elem in (Array)obj) { WriteValue(elem, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IList) { writer.WriteArrayStart(); foreach (object elem in (IList)obj) { WriteValue(elem, writer, writer_is_private, depth + 1); } writer.WriteArrayEnd(); return; } if (obj is IDictionary) { writer.WriteObjectStart(); foreach (DictionaryEntry entry in (IDictionary)obj) { writer.WritePropertyName((string)entry.Key); WriteValue(entry.Value, writer, writer_is_private, depth + 1); } writer.WriteObjectEnd(); return; } Type obj_type = obj.GetType(); // See if there's a custom exporter for the object if (custom_exporters_table.ContainsKey(obj_type)) { ExporterFunc exporter = custom_exporters_table[obj_type]; exporter(obj, writer); return; } // If not, maybe there's a base exporter if (base_exporters_table.ContainsKey(obj_type)) { ExporterFunc exporter = base_exporters_table[obj_type]; exporter(obj, writer); return; } // Last option, let's see if it's an enum if (obj is Enum) { Type e_type = Enum.GetUnderlyingType(obj_type); if (e_type == typeof(long) || e_type == typeof(uint) || e_type == typeof(ulong)) { writer.Write((ulong)obj); } else { writer.Write((int)obj); } return; } // Okay, so it looks like the input should be exported as an // object AddTypeProperties(obj_type); AddInheritMetadata(obj_type); IList <PropertyMetadata> props = type_properties[obj_type]; InheritMetadata im = inherit_metadata[obj_type]; writer.WriteObjectStart(); //如果是允许继承的,把类型也写上 if (im.IsInherit) { writer.WritePropertyName("__type"); WriteValue(obj_type.ToString(), writer, writer_is_private, depth + 1); } //写类的字段和属性 foreach (PropertyMetadata p_data in props) { if (p_data.IsField) { writer.WritePropertyName(p_data.Info.Name); WriteValue(((FieldInfo)p_data.Info).GetValue(obj), writer, writer_is_private, depth + 1); } else { PropertyInfo p_info = (PropertyInfo)p_data.Info; if (p_info.CanRead) { writer.WritePropertyName(p_data.Info.Name); WriteValue(p_info.GetValue(obj, null), writer, writer_is_private, depth + 1); } } } writer.WriteObjectEnd(); }