System.Text.Json 序列化行为

System.Text.Json Serialization Behaviour

我有 3 个 class;它们以下列方式相互包含:

TestClass1
    - TestClass2
        - TestClass3
        - TestClass3
    - TestClass2
        - TestClass3
        - TestClass3

我要做的是序列化然后反序列化这个 class 结构。

这里是 classes:

class TestClass1
{
    public List<object> Data { get; set; }
}

class TestClass2
{
    public string Data1 { get; internal set; }
    public TestClass3 Data2 { get; internal set; }
}

public TestClass3(DateTime dateTime, string v1, string v2, int v3)
{
    this.dateTime = dateTime;
    this.v1 = v1;
    this.v2 = v2;
    this.v3 = v3;
}

我是 运行 的代码在这里:

var data = new List<TestClass2>()
{
    new TestClass2()
    {
        Data1 = "test1",
        Data2 = new TestClass3(new DateTime(2021, 02, 05), "Test", "Test2", 1234)
    },
    new TestClass2()
    {
        Data1 = "test2",
        Data2 = new TestClass3(new DateTime(2021, 02, 06), "Test", "Test3", 1234)
    },
    new TestClass2()
    {
        Data1 = "test1",
        Data2 = new TestClass3(new DateTime(2021, 02, 07), "Test23", "Test2", 5545)
    },
};

var dataStream = new TestClass1()
{
    Data = data.Select(a => (object)a).ToList(),                
};

var streamSerialized = JsonSerializer.Serialize(dataStream);

var objects = JsonSerializer.Deserialize<TestClass1>(streamSerialized);

这里有两个问题

首先,对象没有正确序列化 streamSerialized 不包含 TestClass2.Data2 的任何数据。其次,当我反序列化时,它没有正确反序列化为 class 结构——也就是说,如果我这样做:

var class2 = (TestClass2)objects.Data.First();

我收到这个错误:

System.InvalidCastException: 'Unable to cast object of type 'System.Text.Json.JsonElement' to type 'ConsoleApp1.TestClass2'

反序列化基于作为通用参数提供给 Deserialize() 的类型进行工作,并且对原始类型一无所知。

如果你拿调试器,你会看到发生了什么:

您序列化为 json。 JSON 不包含有关原始类型的任何信息:

var streamSerialized = JsonSerializer.Serialize(dataStream);

你反序列化它并告诉 JsonSerializer 使用来自 TestClass1:

的信息
var objects = JsonSerializer.Deserialize<TestClass1>(streamSerialized);

TestClass1 告诉 JsonSerializer 所有列表项都是 objects:

class TestClass1
{
    public List<object> Data { get; set; }
}

没有任何东西允许序列化程序知道列表项应该是 TestClass2 类型,因此它反序列化为 JsonElements (https://docs.microsoft.com/en-us/dotnet/api/system.text.json.jsonelement?view=net-5.0)

列表

...并且 JsonElement 无法转换为 TestClass2。

第一次修复

public List<TestClass2> Data

现在看看你的 TestClass2:

class TestClass2
{
    public string Data1 { get; internal set; }
    public TestClass3 Data2 { get; internal set; }
}

设置器是内部的,因此该值为空。提供构造函数或使它们 public.

class TestClass2
{
    public string Data1 { get; set; }
    public TestClass3 Data2 { get; set; }
}

有关构造函数的用法,请参阅:https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-immutability?pivots=dotnet-5-0

可以在文档中找到有关一般行为的更多详细信息:https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to?pivots=dotnet-5-0#deserialization-behavior