如何反序列化基础上的父

如何反序列化基础上的父

本文介绍了JSON.NET:如何反序列化基础上的父(持有人)对象的值接口的财产?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的类

class Holder {
    public int ObjType { get; set; }
    public List<Base> Objects { get; set; }
}

abstract class Base {
    // ... doesn't matter
}

class DerivedType1 : Base {
    // ... doesn't matter
}

class DerivedType2 : Base {
    // ... doesn't matter
}

使用的WebAPI我想接收对象并正确反序列化。根据 OBJTYPE 价值,我需要对象来进行反序列化财产无论是作为列表&LT; D​​erivedType1&GT; OBJTYPE == 1 )或列表&LT; D​​erivedType2&GT; OBJTYPE == 2 )。

Using WebAPI I want to receive the object Holder and deserialize it correctly. Based on the ObjType value I need Objects property to be deserialized either as List<DerivedType1> (ObjType == 1) or List<DerivedType2> (ObjType == 2).

目前,我中搜寻和互联网的最好的方法,但我发现最好的是这个答案。这种解决方案的问题在于,它的父对象的宽松环境,所以我无法找到 OBJTYPE 的价值。 OK,我可以创建自定义的 JsonConverter 和remebering的 OBJTYPE 价值,但我依然affraid这行

At the moment I searched SO and internet for best approach, but the best I've found is this answer http://stackoverflow.com/a/8031283/1038496. The problem of this solution is, that it loose context of parent object, so I cannot find out the value of ObjType. OK, I could solve it by creating custom JsonConverter for Holder and remebering the ObjType value, but still I'm affraid of this line

serializer.Populate(jObject.CreateReader(), target);

因为这个答案下面的评论说:

as the comment below this answer says

在ReadJson方法创建的新JsonReader不继承任何原始读者的配置值(文化,DateParseHandling,DateTimeZoneHandling,FloatParseHandling等)的。这些值应使用serializer.Populate()新JsonReader之前被复制。

这是我的问题,我自己复制这些值似乎并不干净,我(如果我错过了什么?)

which is problem for me and copying these values by myself doesn't seem clean to me (what if I miss something?)

所以,问题是:有没有更好的方法我已经错过了基于parent属性值进行反序列化抽象的对象属性

推荐答案

您是在正确的轨道上。你需要实现一个自定义的 JsonConverter 类来处理这种情况下,如你所说。但是,不要担心,这是可以编写转换器以这样一种方式,你可以使用传递到转换器的原始阅读器和串行情况下,从来没有需要到设置在复制到新的实例。下面是我会怎么写:

You are on the right track. You do need to implement a custom JsonConverter for your Holder class to handle this situation, as you suggested. But, don't worry, it is possible to write the converter in such a way that you can use the original reader and serializer instances passed to the converter, without ever needing to copy the settings over to new instances. Here is how I would write it:

class HolderConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Holder));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        Holder holder = new Holder();
        holder.ObjType = (int)jo["ObjType"];
        holder.Objects = new List<Base>();
        foreach (JObject obj in jo["Objects"])
        {
            if (holder.ObjType == 1)
                holder.Objects.Add(obj.ToObject<DerivedType1>(serializer));
            else
                holder.Objects.Add(obj.ToObject<DerivedType2>(serializer));
        }
        return holder;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

下面是一个快速演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        [
            {
                ""ObjType"" : 1,
                ""Objects"" :
                [
                    { ""Id"" : 1, ""Foo"" : ""One"" },
                    { ""Id"" : 2, ""Foo"" : ""Two"" },
                ]
            },
            {
                ""ObjType"" : 2,
                ""Objects"" :
                [
                    { ""Id"" : 3, ""Bar"" : ""Three"" },
                    { ""Id"" : 4, ""Bar"" : ""Four"" },
                ]
            },
        ]";

        List<Holder> list = JsonConvert.DeserializeObject<List<Holder>>(json);

        foreach (Holder holder in list)
        {
            if (holder.ObjType == 1)
            {
                foreach (DerivedType1 obj in holder.Objects)
                {
                    Console.WriteLine("Id: " + obj.Id + "  Foo: " + obj.Foo);
                }
            }
            else
            {
                foreach (DerivedType2 obj in holder.Objects)
                {
                    Console.WriteLine("Id: " + obj.Id + "  Bar: " + obj.Bar);
                }
            }
        }
    }
}

[JsonConverter(typeof(HolderConverter))]
class Holder
{
    public int ObjType { get; set; }
    public List<Base> Objects { get; set; }
}

abstract class Base
{
    public int Id { get; set; }
}

class DerivedType1 : Base
{
    public string Foo { get; set; }
}

class DerivedType2 : Base
{
    public string Bar { get; set; }
}

输出:

Id: 1  Foo: One
Id: 2  Foo: Two
Id: 3  Bar: Three
Id: 4  Bar: Four

这篇关于JSON.NET:如何反序列化基础上的父(持有人)对象的值接口的财产?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 11:36