序列化/反序列化派生类型

本文关键字:类型 派生 反序列化 序列化 | 更新日期: 2023-09-27 18:17:58

json.net (newtonsoft)
我正在看文档,但我找不到任何关于这个或最好的方法。

public class Base
{
    public string Name;
}
public class Derived : Base
{
    public string Something;
}
JsonConvert.Deserialize<List<Base>>(text);

现在我在序列化列表中有了派生对象。如何反序列化列表并返回派生类型?

序列化/反序列化派生类型

您必须启用类型名称处理,并将其作为序列化和反序列化操作的设置参数传递给(反)序列化器。

Base object1 = new Base() { Name = "Object1" };
Derived object2 = new Derived() { Something = "Some other thing" };
List<Base> inheritanceList = new List<Base>() { object1, object2 };
JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
string Serialized = JsonConvert.SerializeObject(inheritanceList, settings);
List<Base> deserializedList = JsonConvert.DeserializeObject<List<Base>>(Serialized, settings);

这将导致派生类的正确反序列化。它的一个缺点是它将命名您正在使用的所有对象,因此它将命名您将对象放入的列表。

如果您将类型存储在text中(在本场景中应该是这样),则可以使用JsonSerializerSettings

参见:如何将JSON反序列化为IEnumerable使用Newtonsoft JSON。净

不过要小心。使用TypeNameHandling = TypeNameHandling.None以外的任何东西都可能使您暴露于安全漏洞。

既然这个问题很受欢迎,那么如果您想要控制类型属性名称及其值,那么添加该如何做可能会很有用。

较长的方法是编写自定义JsonConverter s,通过手动检查和设置type属性来处理(反)序列化。

一个更简单的方法是使用JsonSubTypes,它通过属性处理所有的样板文件:

[JsonConverter(typeof(JsonSubtypes), "Sound")]
[JsonSubtypes.KnownSubType(typeof(Dog), "Bark")]
[JsonSubtypes.KnownSubType(typeof(Cat), "Meow")]
public class Animal
{
    public virtual string Sound { get; }
    public string Color { get; set; }
}
public class Dog : Animal
{
    public override string Sound { get; } = "Bark";
    public string Breed { get; set; }
}
public class Cat : Animal
{
    public override string Sound { get; } = "Meow";
    public bool Declawed { get; set; }
}

使用这个JsonKnownTypes,使用方式很相似,只是在json中添加了discriminator:

[JsonConverter(typeof(JsonKnownTypeConverter<BaseClass>))]
[JsonKnownType(typeof(Base), "base")]
[JsonKnownType(typeof(Derived), "derived")]
public class Base
{
    public string Name;
}
public class Derived : Base
{
    public string Something;
}

现在当你在json中序列化对象时,将添加"$type""base""derived"的值,它将用于反序列化

序列化列表示例:

[
    {"Name":"some name", "$type":"base"},
    {"Name":"some name", "Something":"something", "$type":"derived"}
]

在。net 6/7中你可以使用

[JsonDerivedType(typeof(Panel), typeDiscriminator: "panel")]

见https://learn.microsoft.com/en - us/dotnet/api/system.text.json.serialization.jsonderivedtypeattribute. ctor?view=net - 7.0, f1url = % 3 fappid % 3 ddev16idef1 % 26 l % 3 den-us % 26 k % 3 dk(2523男星System.Text.Json.Serialization.JsonDerivedTypeAttribute. %) % 3 bk (DevLang-csharp) % 26rd % 3 dtrue

在Serialize方法中添加对象

 var jsonMessageBody = JsonSerializer.Serialize<object>(model);