Custom Json converter for a collection of a container with polymorphic properties

限于喜欢 提交于 2019-12-13 20:36:40

问题


I am working on complex data transfer for Web API. it suppose to send structure that has a collection of classes with nested polymorphic properties. The default JSON Converter doesn't recognize polymorphic structures by default. I tried to use the full namespace resolution. Unfortunately, in my scenario it didn't work as i have different frameworks (Full framework and .net core) on the client server sides and it doesn't resolve it properly namespaces and assemblies. (yes I tried mapping of Assemblies and Namespaces and realized that it is gonna be unsupportable mess)

I think custom converter should make it work, unfortunately I have no much knowledge of how to write it properly.

The data structure is like following:

I have a main context with some properties and a Collection of Containers. Each Container has the polymorphic properties that at the serializing should be resolved with extra parameter 'type' that contains the class name

Issue:

I fixed all the issues in this sample , the code is completely working

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

来源:https://stackoverflow.com/questions/49756595/custom-json-converter-for-a-collection-of-a-container-with-polymorphic-propertie

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!