【问题标题】:JSON deserialization into C# class hierarchy [duplicate]JSON反序列化为C#类层次结构[重复]
【发布时间】:2021-05-06 00:30:21
【问题描述】:

我从一个网络钩子中获取 JSON,其中对象的类型被烘焙到 JSON 本身中,有点像这样:

“a”类型的数据示例:

{
    "type": "a",
    "name": "object name",
    "a_data": "something specific to type a"
}

以及“b”类型的数据示例:

{
    "type": "b",
    "name": "another object name",
    "b_data": {
        "b_field1": "Something specific to type b",
        "b_field2": "Something else specific to type b"
    }

我保证每个有效载荷都会有一个type 和一个name 属性。 type "a" 的所有有效负载将额外具有 a_data 属性,type b 的所有有效负载将额外具有b_data 属性,其本身由属性b_field1b_field2 组成。

(当然这非常简化来说明这个问题 - 真正的用例有更长更复杂的 json 和更多类型)

我想反序列化为 C# 类,建模一个基类(至少包含 name 属性和可能的​​ type 属性)和两个派生类,一个用于在 type 中序列化的对象"a" json,一个用于在type "b" json 中序列化的对象。

我会想象定义 C# 类,例如:

    public class Base
    {
        public string type { get; set; }
        public string name { get; set; }
    }

    public class DeriviedA: Base
    {
        public string a_data { get; set; }
    }

    public class DervivedB : Base
    {
        public class DataB
        {
            public string b_field1 { get; set; }
            public string b_field2 { get; set; }
        }

        public DataB b_data { get; set; }
    }

鉴于我不知道有效负载何时传入它是什么类型,我需要根据传入类型有条件地反序列化。但是在我反序列化之前我不“知道”那是什么类型。我很确定以下方法会起作用,但这不是一个特别好的解决方案,因为这意味着我需要反序列化两次:

        public static Base Deserialize(string incomingJson)
        {
            Base tmp = JsonConvert.DeserializeObject<Base>(incomingJson);
            switch (tmp.type)
            {
                case "a":
                    return JsonConvert.DeserializeObject<DerivedA>(incomingJson);
                case "b":
                    return JsonConvert.DeserializeObject<DerivedB>(incomingJson);
                default:
                    throw new InvalidOperationException($"unable to deserialize payload of type {tmp.type}");
            }
        }

现在,除了需要进行不正常的双重反序列化之外,请注意,我无法将 Base 类标记为 abstract,即使我从不想要 Base 类本身的实例化。

无论如何,我对这样做的想法、策略或最佳实践感到好奇。我的偏好是使用 Newtonsoft 进行反序列化,但这不是要求

【问题讨论】:

    标签: c# json.net json-deserialization


    【解决方案1】:

    在使用序列化程序之前,只需使用非反序列化 JSON 阅读器来嗅探类型。

    Newtonsoft 有一个非常简单的方法来做到这一点:

    dynamic message = JObject.Parse(json);
    string type = message.type;
    

    https://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm

    【讨论】:

      猜你喜欢
      • 2017-02-21
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 1970-01-01
      相关资源
      最近更新 更多