使用jsonderivedType属性来序列化和验证.NET 7中的多态性对象

发布于 2025-02-13 14:51:37 字数 2169 浏览 1 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

演多会厌 2025-02-20 14:51:37

该过程在文档中描述: https://learn.microsoft.com/en-us/dotnet/standard/serialization/serialization/system-stemm-text-json/polymorphism?

要启用多态性的挑选化,您必须为派生类指定类型的歧视器
...随着添加的元数据,特别是类型鉴别器,序列化器可以序列化并进行有效载荷化
...序列化将与类型的区分元数据一起发射JSON

从本质上讲,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

To enable polymorphic deserialization, you must specify a type discriminator for the derived class
... With the added metadata, specifically, the type discriminator, the serializer can serialize and deserialize the payload
... Serialization will emit JSON along with the type discriminator metadata

Essentially, the JsonDerivedTypeAttribute identifies supported derived types and adds the type discriminator $type as JSON metadata, which in turn instructs the serializer.

梦断已成空 2025-02-20 14:51:37

抱歉,我没有注意序列化对象。它包含:“ $ 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文