继承 Newtonsoft JSON.NET 的反序列化无法正常工作
Deserialization with inheritance Newtonsoft JSON.NET not working properly
(使用 Newtonsoft JSON.NET)
你好我在反序列化事件列表时遇到问题,其中事件是基本类型,例如ResourceEvent 是一个子类。如果我只是进行序列化然后反序列化一切正常并且列表包含 ResourceEvents - 但是我将使用 EF7 的那些存储到 postgres 的 jsonb 列中。
当我从 postgres 获得 JSON 有效负载时,它已重新排序(但 JSON 合法)属性。当我尝试使用 Newtonsoft JSON.net 进行反序列化时,它只给我一个包含基本类型 Event 而不是子类 ResourceEvent 的列表。
我添加了两个高度剥离的示例,不同之处在于 "Type" 属性 位于不同的位置。 类 中其他属性的顺序也被打乱了。我在 类 上根本没有注释。
此负载成功反序列化:
json
{
"$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib",
"$values": [
{
"$type": "ResourceConfigurationEvent, Tests",
/* Properties */
"Resources": {
/* Properties */
},
"Type": 1
}
]
}
此负载反序列化失败:
json
{
"$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib",
"$values": [
{
"Type": 1,
"$type": "ResourceConfigurationEvent, Tests",
/* Properties */
"Resources": {
/* Properties */
},
}
]
}
Json.Net 通常期望 $type
元数据是每个对象的第一个 属性,以实现反序列化的最佳效率。如果 $type
没有首先出现,则 Json.Net 假定它不存在。这就是为什么在重新排序属性时会得到不同结果的原因。
幸运的是,Json.Net提供了一个MetadataPropertyHandling
设置,让它可以应对这种情况。如果您将 MetadataPropertyHandling
设置为 ReadAhead
它应该可以解决您的问题。请注意,这会对性能产生影响。
这是来自文档的 code sample。
string json = @"{
'Name': 'James',
'Password': 'Password1',
'$type': 'MyNamespace.User, MyAssembly'
}";
object o = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
// $type no longer needs to be first
MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
});
User u = (User)o;
Console.WriteLine(u.Name);
// James
(使用 Newtonsoft JSON.NET)
你好我在反序列化事件列表时遇到问题,其中事件是基本类型,例如ResourceEvent 是一个子类。如果我只是进行序列化然后反序列化一切正常并且列表包含 ResourceEvents - 但是我将使用 EF7 的那些存储到 postgres 的 jsonb 列中。
当我从 postgres 获得 JSON 有效负载时,它已重新排序(但 JSON 合法)属性。当我尝试使用 Newtonsoft JSON.net 进行反序列化时,它只给我一个包含基本类型 Event 而不是子类 ResourceEvent 的列表。
我添加了两个高度剥离的示例,不同之处在于 "Type" 属性 位于不同的位置。 类 中其他属性的顺序也被打乱了。我在 类 上根本没有注释。
此负载成功反序列化:
json
{
"$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib",
"$values": [
{
"$type": "ResourceConfigurationEvent, Tests",
/* Properties */
"Resources": {
/* Properties */
},
"Type": 1
}
]
}
此负载反序列化失败:
json
{
"$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib",
"$values": [
{
"Type": 1,
"$type": "ResourceConfigurationEvent, Tests",
/* Properties */
"Resources": {
/* Properties */
},
}
]
}
Json.Net 通常期望 $type
元数据是每个对象的第一个 属性,以实现反序列化的最佳效率。如果 $type
没有首先出现,则 Json.Net 假定它不存在。这就是为什么在重新排序属性时会得到不同结果的原因。
幸运的是,Json.Net提供了一个MetadataPropertyHandling
设置,让它可以应对这种情况。如果您将 MetadataPropertyHandling
设置为 ReadAhead
它应该可以解决您的问题。请注意,这会对性能产生影响。
这是来自文档的 code sample。
string json = @"{
'Name': 'James',
'Password': 'Password1',
'$type': 'MyNamespace.User, MyAssembly'
}";
object o = JsonConvert.DeserializeObject(json, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
// $type no longer needs to be first
MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
});
User u = (User)o;
Console.WriteLine(u.Name);
// James