使用继承进行反序列化Newtonsoft JSON.NET无法正常工作

时间:2016-06-01 08:41:27

标签: c# json postgresql json.net jsonb

(使用Newtonsoft JSON.NET)

您在反序列化事件列表时遇到问题,其中Event是基本类型,例如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 */                
            },
        }
    ]
}

1 个答案:

答案 0 :(得分:4)

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