使用jsonderivedType属性来序列化和验证.NET 7中的多态性对象
JSON.NET(由Newtonsoft)在序列化和估算复杂对象方面有很大的支持。
我很好奇使用system.text.json
而不是json.net,我无法在Internet上找到一个好的教程。
.NET 7预览支持应对多态对象。这是一个使用.NET 7预览和C#11的示例:
// _To run it you will need net7 preview and c# 11_
using System.Text.Json.Serialization;
var testPolymorphism = new TestPolymorphysm()
{
Animals = new List<Animal>()
{
new Fish() {
Id = "fish1",
Name = "GoldFish",
Action = new ActionSwim() { DistanceSwam = 10 }
},
new Dog() {
Id = "dog1",
Name = "Tom",
Action = new ActionRun() { DistanceRan = 50 }
}
}
};
// serialize
var jsonSerialized = System.Text.Json.JsonSerializer.Serialize(testPolymorphism);
Console.WriteLine(jsonSerialized);
// deserialize
var clonePolymorphysm = System.Text.Json.JsonSerializer.Deserialize<TestPolymorphysm>(jsonSerialized);
Console.WriteLine(clonePolymorphysm);
// === MODELS ===
class TestPolymorphysm
{
public List<Animal> Animals { get; set; } = new();
}
[JsonDerivedType(derivedType: typeof(Dog), typeDiscriminator: "foo1")]
[JsonDerivedType(derivedType: typeof(Fish), typeDiscriminator: "foo2")]
abstract class Animal
{
public required string Id { get; set; }
public required string Name { get; set; }
}
class Dog : Animal
{
public required IAction Action { get; set; }
public AnimalType ExtensionType => AnimalType.Dog;
}
class Fish : Animal
{
public required IAction Action { get; set; }
public AnimalType ExtensionType => AnimalType.Fish;
}
[JsonDerivedType(derivedType: typeof(ActionSwim), typeDiscriminator: "foo3")]
[JsonDerivedType(derivedType: typeof(ActionRun), typeDiscriminator: "foo4")]
interface IAction { }
class ActionSwim : IAction
{
public required int DistanceSwam { get; set; }
}
class ActionRun : IAction
{
public required int DistanceRan { get; set; }
}
public enum AnimalType
{
Fish,
Dog
}
无论如何,此代码都可以通过JSONDERIVEDTYPE
属性来工作,但我不确定它为什么有效。为什么如果我删除键入的歧义器foo1,foo2,foo3和foo4,那就不起作用?我想确保在使用之前了解它的工作原理。
JSON.NET (by Newtonsoft) has great support for serializing and deserializing complex objects.
I am curious about using System.Text.Json
instead of JSON.NET and I am not able to find a good tutorial on the internet.
The .NET 7 preview has support for deserializing polymorphic objects. Here is an example using .NET 7 preview and C# 11:
// _To run it you will need net7 preview and c# 11_
using System.Text.Json.Serialization;
var testPolymorphism = new TestPolymorphysm()
{
Animals = new List<Animal>()
{
new Fish() {
Id = "fish1",
Name = "GoldFish",
Action = new ActionSwim() { DistanceSwam = 10 }
},
new Dog() {
Id = "dog1",
Name = "Tom",
Action = new ActionRun() { DistanceRan = 50 }
}
}
};
// serialize
var jsonSerialized = System.Text.Json.JsonSerializer.Serialize(testPolymorphism);
Console.WriteLine(jsonSerialized);
// deserialize
var clonePolymorphysm = System.Text.Json.JsonSerializer.Deserialize<TestPolymorphysm>(jsonSerialized);
Console.WriteLine(clonePolymorphysm);
// === MODELS ===
class TestPolymorphysm
{
public List<Animal> Animals { get; set; } = new();
}
[JsonDerivedType(derivedType: typeof(Dog), typeDiscriminator: "foo1")]
[JsonDerivedType(derivedType: typeof(Fish), typeDiscriminator: "foo2")]
abstract class Animal
{
public required string Id { get; set; }
public required string Name { get; set; }
}
class Dog : Animal
{
public required IAction Action { get; set; }
public AnimalType ExtensionType => AnimalType.Dog;
}
class Fish : Animal
{
public required IAction Action { get; set; }
public AnimalType ExtensionType => AnimalType.Fish;
}
[JsonDerivedType(derivedType: typeof(ActionSwim), typeDiscriminator: "foo3")]
[JsonDerivedType(derivedType: typeof(ActionRun), typeDiscriminator: "foo4")]
interface IAction { }
class ActionSwim : IAction
{
public required int DistanceSwam { get; set; }
}
class ActionRun : IAction
{
public required int DistanceRan { get; set; }
}
public enum AnimalType
{
Fish,
Dog
}
Anyways this code works thanks to JsonDerivedType
attributes but I am not sure why it works. Why is it that if I remove the typeDiscriminators foo1, foo2, foo3 and foo4 it does not work? I want to make sure I understand how it works before I use it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该过程在文档中描述: https://learn.microsoft.com/en-us/dotnet/standard/serialization/serialization/system-stemm-text-json/polymorphism?
从本质上讲,
jsonDerivedTypeAttribute
nidefed 识别支持的派生类型,并添加了类型的歧视器$ type
作为JSON元数据序列化器。The process is described in the documentation: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0#polymorphic-type-discriminators
Essentially, the
JsonDerivedTypeAttribute
identifies supported derived types and adds the type discriminator$type
as JSON metadata, which in turn instructs the serializer.抱歉,我没有注意序列化对象。它包含:
“ $ type”:“ foo1”,
,“ $ type”:“ foo2”,
等。这就是为什么Deserialializer知道如何对象进行挑选。
Sorry I was not paying attention to the serialized object. It contains:
"$type": "foo1",
,"$type": "foo2",
etc..That's why the deserializer knows how to deserialize the object.