【发布时间】: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_field1 和b_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