简体   繁体   English

C#Newtonsoft-根据属性名称将JSON反序列化为具体的

[英]C# Newtonsoft - Deserialize JSON into concrete based on property name

I've got a JSON coming in that I'd like to deserialize into a class A ; 我有一个JSON,我想反序列化为A类; one of the fields is an array of abstract class B (which has a few concrete implementations). 字段之一是一组抽象类B (有一些具体的实现)。 Is it possible to deserialize the abstract-class array correctly without building a custom JsonConverter? 是否可以在构建自定义JsonConverter的情况下正确地反序列化抽象类数组? Ideally, something native to JSON.net and not verbose, eg with TypeNameHandling.All ... but I haven't got that particular route to work. 理想情况下,JSON.net本身并不冗长,例如使用TypeNameHandling.All ...,但是我没有那条特定的途径可以工作。

I do not have access to the JSON at serialization-time (if I did, TypeNameHandling would work great), but only at deserialization-time. 没有在序列化时访问JSON(如果可以的话, TypeNameHandling会很好用),但只能在反序列化时使用。

To be concrete: 具体来说:

public class A  // the top-level class to deserialize
{
    public B[] arr;
    // other members...
}
public abstract class B
{
    // ...some fields...
}
public class C : B 
{
    // a concrete implementation of B
}
public class D : B 
{
    // another concrete implementation of B
}

And I receive a JSON that may look like: 而且我收到了一个看起来像这样的JSON:

{
  "arr" : [
   {
     // a C object
   },
   {
     // a D object
   }
  ]
}

I know you can effectively do something like this really cleanly with XML deserialization using the below; 我知道您可以使用下面的XML反序列化来有效地干净地做这样的事情: I'm pretty much looking for something similar in JSON. 我几乎在寻找与JSON类似的东西。

// tells the deserializer to deserialize the object with field name "C" as a 
// class C, and field name "D" as a D
[XmlElement("C", Type = typeof(C))]
[XmlElement("D", Type = typeof(D))]
public B[] arr;

Since you are unable to modify the JSON to use TypeNameHandling you need to create a custom converter that examines the properties to determine which type to return. 由于您无法修改JSON以使用TypeNameHandling ,因此需要创建一个自定义转换器,以检查属性以确定要返回的类型。 Let's say you had your derived classes looking like this for example: 假设您的派生类如下所示:

public class C : B
{
    public string CProperty { get; set; }
}

public class D : B
{
    public string DProperty { get; set; }
}

You could have a custom converter class that looks like this: 您可能有一个自定义转换器类,如下所示:

public class BConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type type, 
        object value, JsonSerializer serializer)
    {
        JObject jobject = JObject.Load(reader);
        if (jobject.ContainsKey("CProperty"))
        {
            return jobject.ToObject<C>(serializer);
        }

        if (jobject.ContainsKey("DProperty"))
        {
            return jobject.ToObject<D>(serializer);
        }

        throw new Exception("Um, this is some other type!");
    }

    public override bool CanConvert(Type type) => type == typeof(B);
    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
        => throw new NotImplementedException();
}

Now you can deserialise like this: 现在您可以像这样反序列化:

var result = JsonConvert.DeserializeObject<A>(json, new BConverter());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM