使用继承牛顿软件的反序列化 JSON.NET 无法正常工作



(使用 Newtonsoft JSON.NET)

嗨,我在反序列化事件列表时遇到了问题,其中事件是基本类型,例如 ResourceEvent 是一个子类。如果我只是进行序列化然后反序列化一切正常,并且列表包含 ResourceEvents - 但是我将使用 EF7 的那些存储到 postgres 中的 jsonb 列中。

当我从 postgres 获取 JSON 有效负载时,它已对属性进行了重新排序(但 JSON 合法)。当我尝试使用Newtonsoft反序列化时 JSON.net 它只给了我一个基本类型事件的列表,而不是子类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它应该可以解决您的问题。 请注意,这将对性能产生影响。

下面是文档中的代码示例。

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

相关内容

  • 没有找到相关文章

最新更新