简体   繁体   English

具有继承功能的反序列化Newtonsoft JSON.NET无法正常工作

[英]Deserialization with inheritance Newtonsoft JSON.NET not working properly

(Using Newtonsoft JSON.NET) (使用Newtonsoft JSON.NET)

Hi I've got a problem when deserializing a list of events where Event is the base type and eg ResourceEvent is a subclass. 嗨,我在反序列化事件列表时遇到问题,其中Event是基本类型,例如ResourceEvent是子类。 If I just do a serialize and then deserialize everything works ok and the list contains the ResourceEvents - however I store those using EF7 into a jsonb column in postgres. 如果我只是进行序列化然后反序列化,一切正常,并且列表包含ResourceEvents-但是,我将使用EF7的事件存储在postgres中的jsonb列中。

When I get the JSON payload from postgres it has reordered (but JSON legal) the properties. 当我从postgres获取JSON有效负载时,它已经对属性进行了重新排序(但JSON合法)。 When I try to deserialize using Newtonsoft JSON.net it only give me a list with base types Event and not the subclass ResourceEvent. 当我尝试使用Newtonsoft JSON.net进行反序列化时,它只给我列出了具有基本类型Event而不是子类ResourceEvent的列表。

I've added the two highly stripped examples where the differences is where the "Type" property is on different places. 我添加了两个高度剥离的示例,区别在于“ Type”属性在不同位置。 The ordering of other properties has also been scrambeled in the classes. 在类中还对其他属性的顺序进行了排序。 I've got no annotations on the classes at all. 我根本没有在类上的注释。

This payload successfully deseralizes: 此有效载荷成功地反硝化:

json
{
    "$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib",
    "$values": [
        {
            "$type": "ResourceConfigurationEvent, Tests",
            /* Properties */
            "Resources": {
                /* Properties */                
            },
            "Type": 1            
        }
    ]
}

This payload unsuccessfully deserializes: 该有效负载未能成功反序列化:

json
{
    "$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib",
    "$values": [
        {
            "Type": 1,            
            "$type": "ResourceConfigurationEvent, Tests",
            /* Properties */
            "Resources": {
                /* Properties */                
            },
        }
    ]
}

Json.Net normally expects the $type metadata to be the first property of each object for best efficiency in deserialization. Json.Net通常期望$type元数据是每个对象的第一个属性,以实现反序列化的最佳效率。 If the $type does not appear first, then Json.Net assumes it isn't there. 如果$type没有首先出现,则Json.Net假定它不存在。 That is why you are getting different results when the properties are reordered. 这就是为什么对属性重新排序时会得到不同结果的原因。

Fortunately, Json.Net provides a MetadataPropertyHandling setting to allow it to cope with this situation. 幸运的是,Json.Net提供了MetadataPropertyHandling设置,以使其能够应对这种情况。 If you set MetadataPropertyHandling to ReadAhead it should solve your problem. 如果将MetadataPropertyHandling设置为ReadAhead则应该可以解决您的问题。 Note that this will have an impact on performance. 请注意,这将对性能产生影响。

Here is a code sample from the documentation. 这是文档中的代码示例

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM