自定义Json转换器,用于具有多态属性的容器的集合

时间:2018-04-10 14:45:03

标签: c# json json.net

我正在为Web API进行复杂的数据传输。它假设发送具有嵌套多态属性的类集合的结构。默认情况下,默认的JSON转换器无法识别多态结构。 我试图使用完整的命名空间解析。不幸的是,在我的场景中,它没有工作,因为我在客户端服务器端有不同的框架(完整框架和.net核心),它没有正确解析它的命名空间和程序集。 (是的,我尝试了程序集和命名空间的映射,并意识到它将是无法支持的混乱)

我认为自定义转换器应该能够正常工作,遗憾的是我对如何正确编写它并不了解。

数据结构如下:

我有一个带有一些属性的主上下文和一个容器集合。 每个Container都具有多态属性,序列化应该使用包含类名的额外参数'type'来解析

问题:

我修复了此示例中的所有问题,代码完全正常工作

   public class MyConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteStartArray();

        var t = value as List<Container>;

        foreach (var e in t)
        {
            var container = new JObject();

            var fi = e.PropertyA;
            JObject o = JObject.FromObject(fi);
            o.AddFirst(new JProperty("type", new JValue(fi.GetType().Name)));

            container.Add(new JProperty("PropertyA", o));

            var res = e.PropertyB;
            o = JObject.FromObject(res);
            o.AddFirst(new JProperty("type", new JValue(res.GetType().Name)));

            container.Add(new JProperty("PropertyB", o));

            container.WriteTo(writer);
        }
        writer.WriteEndArray();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return string.Empty;
        }
        else if (reader.TokenType == JsonToken.String)
        {
            return serializer.Deserialize(reader, objectType);
        }
        else
        {
            JArray array = JArray.Load(reader);

            List<Container> collection = new List<Container>();

            foreach (var item in array.Children())
            {
                JToken propATkn = item.First;
                JToken propBTkn = propATkn.Next;

                var strType = ((JProperty)(propATkn.OfType<JObject>()).First().First).Value.ToString();


                Type type = Type.GetType(strType);

                BaseClassA propA = propATkn.OfType<JObject>().FirstOrDefault().ToObject(type) as BaseClassA;

                strType = ((JProperty)(propBTkn.OfType<JObject>()).First().First).Value.ToString();

                type = Type.GetType(strType);

                BaseClassB propB = propBTkn.OfType<JObject>().FirstOrDefault().ToObject(type) as BaseClassB;

                collection.Add(new Container { PropertyA = propA, PropertyB = propB});
            }

            return collection;
        }
    }

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

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}



    public class Context
{
    [JsonConverter(typeof(MyConverter))]
    public IList<Container> sources { get; set; } = new List<Container>();

    public int Value { get; set; }

    public string Key { get; set; }
}

public class Container
{
    public BaseClassA PropertyA { get; set; }

    public BaseClassB PropertyB { get; set; }
}

    public class BaseClassB
{
    public int B;
}

public class ClassBA : BaseClassB
{
    public int BA;
}

public class ClassBB : BaseClassB
{
    public int BB;
}

public class BaseClassA
{
    public int A;
}

public class ClassAA : BaseClassA
{
    public int AA;
}

public class ClassAB : BaseClassA
{
    public int AB;
}

0 个答案:

没有答案