【问题标题】:C# Newtonsoft - Deserialize JSON into concrete based on property nameC# Newtonsoft - 根据属性名称将 JSON 反序列化为具体的
【发布时间】:2018-08-25 21:46:03
【问题描述】:

我有一个 JSON 进来,我想反序列化成一个类 A;其中一个字段是抽象类B 的数组(它有一些具体的实现)。是否可以正确地反序列化抽象类数组而不构建自定义 JsonConverter?理想情况下,JSON.net 原生的东西,而不是冗长的,例如与TypeNameHandling.All... 但我没有那条特定的工作路线。

我确实可以在序列化时访问 JSON(如果我这样做,TypeNameHandling 会很好用),但只能在反序列化时访问。

具体来说:

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
}

我收到的 JSON 可能如下所示:

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

我知道你可以使用下面的 XML 反序列化来有效地做这样的事情;我非常想在 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;

【问题讨论】:

  • 你知道JSON会有C还是D的项目吗?
  • @CamiloTerevinto 不。该数组可能只有 Cs、Ds 或 Cs 和 Ds 的某种组合
  • 你是否分别得到它们(比如用不同的方法)?我的意思是,如果您在编译时知道它们是 C 还是 D
  • @CamiloTerevinto 不幸的是没有。整个 JSON 将一次性完成。
  • 有趣的问题。如果没有自定义转换器来检查属性,我不确定你会怎么做。

标签: c# .net json json.net json-deserialization


【解决方案1】:

由于您无法修改 JSON 以使用 TypeNameHandling,您需要创建一个自定义转换器来检查属性以确定要返回的类型。假设您的派生类看起来像这样:

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

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

您可以有一个如下所示的自定义转换器类:

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

现在你可以像这样反序列化:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多