具有多态对象的数组的 JSON 序列化 [英] JSON serialization of array with polymorphic objects
问题描述
是否可以使用 .NET 标准 JavascriptSerializer/JsonDataContractSerializer 或外部解析器,使用包含对象类型的包装器方法来序列化对象数组?
Is it possible with .NET standard JavascriptSerializer/JsonDataContractSerializer or external parsers, to serialize objects array using a wrapper approach including the object type?
例如,从列表生成此 JSON:
For example, to generate this JSON from a List:
[{ 'dog': { ...dog properties... } },
{ 'cat': { ...cat properties... } }]
而不是典型:
[{ ...dog properties... },
{ ...cat properties... }]
使用 JsonTypeInfo.As.WRAPPER_OBJECT 属性在 Java 中使用 JsonTypeInfo.As.WRAPPER_OBJECT 属性可以做到这一点.
This is doable in Java with Jackson using JsonTypeInfo.As.WRAPPER_OBJECT attribute.
推荐答案
Json.NET 有一个巧妙的解决方案.有一个设置可以智能地添加类型信息——像这样声明:
Json.NET has a neat solution for this. There is a setting that intelligently adds type information - declare it like this:
new JsonSerializer { TypeNameHandling = TypeNameHandling.Auto };
这将确定是否需要类型嵌入并在必要时添加它.假设我有以下课程:
This will determine whether type embedding is required and add it where necessary. Lets say I had the following classes:
public class Message
{
public object Body { get; set; }
}
public class Person
{
public string Name { get; set; }
}
public class Manager : Person
{
}
public class Department
{
private List<Person> _employees = new List<Person>();
public List<Person> Employees { get { return _employees; } }
}
注意 Message Body 是 object 类型,Manager 是 Person 的子类.如果我使用具有单个经理的部门正文序列化消息,我会得到:
Notice the Message Body is of type object, and that Manager subclasses Person. If I serialize a Message with a Department Body that has a single Manager I get this:
{
"Body":
{
"$type":"Department, MyAssembly",
"Employees":[
{
"$type":"Manager, MyAssembly",
"Name":"Tim"
}]
}
}
注意它是如何添加 $type 属性来描述部门和经理类型的.如果我现在在员工列表中添加一个人员并将消息正文更改为部门类型,如下所示:
Notice how it's added the $type property to describe the Department and Manager types. If I now add a Person to the Employees list and change the Message Body to be of type Department like this:
public class Message
{
public Department Body { get; set; }
}
然后不再需要 Body 类型注释并且新的 Person 没有被注释 - 没有注释假设元素实例是声明的数组类型.序列化后的格式变为:
then the Body type annotation is no longer needed and the new Person is not annotated - absence of annotation assumes the element instance is of the declared array type. The serialized format becomes:
{
"Body":
{
"Employees":[
{
"$type":"Manager, MyAssembly",
"Name":"Tim"
},
{
"Name":"James"
}]
}
}
这是一种有效的方法 - 仅在需要时添加类型注释.虽然这是特定于 .NET 的,但该方法足够简单,可以处理其他平台上的反序列化器/消息类型应该很容易扩展来处理这个问题.
This is an efficient approach - type annotation is only added where required. While this is .NET specific, the approach is simple enough to handle that deserializers/message types on other platforms should be fairly easily extended to handle this.
不过,我不会在公共 API 中使用它,因为它是非标准的.在这种情况下,您需要避免多态性,并使消息中的版本控制和类型信息成为非常明确的属性.
I'd be reticent about using this in a public API though, as it is non-standard. In that case you'd want to avoid polymorphism, and make versioning and type information very explicit properties in the message.
这篇关于具有多态对象的数组的 JSON 序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!