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 所有列表项都是 object
s:
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
我有 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 所有列表项都是 object
s:
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