Beispiel #1
0
        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;
                }
            }
        }
Beispiel #2
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 (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);
        }
Beispiel #3
0
        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();
        }