【问题标题】:Newtonsoft JSON.net deserialization error where fields in JSON change orderNewtonsoft JSON.net 反序列化错误,其中 JSON 中的字段更改顺序
【发布时间】:2015-06-12 03:36:37
【问题描述】:

这是一个从安卓设备获取请求的 WCF 服务。 相同的请求适用于 Lollipop 设备,而不适用于 jellybean 设备,因为 jellybean 在创建时对 JSON 的排列方式不同。

例外:

反序列化对象时出现意外标记:字符串。路径“SearchFilters.config.$type”,第 1 行,位置 212。

非工作Json:

{
    "DeviceType": 2,
    "SearchFilters": {
        "config": {
            "$values": [
                {
                    "Collection": {
                        "DeviceType": 2
                    },
                    "Category": ""
                }
            ],
            "$type": "System.Collections.Generic.List`1[[Yoosh.SharedClasses.YooshConfig, YooshSharedClassesDll]], mscorlib"
        }
    },
    "RequestingUserId": "66666666-6666-6666-6666-666666666666",
    "APIKey": "xxx"
}

工作 Json:

{
    "APIKey": "xxx",
    "DeviceType": 2,
    "RequestingUserId": "66666666-6666-6666-6666-666666666666",
    "SearchFilters": {
        "config": {
            "$type": "System.Collections.Generic.List`1[[Yoosh.SharedClasses.YooshConfig, YooshSharedClassesDll]], mscorlib",
            "$values": [
                {
                    "Category": "",
                    "Collection": {
                        "DeviceType": 2
                    }
                }
            ]
        }
    }
}

某些字段的顺序不同。这是唯一的区别。

C# 类:

public class QueryParameters 
{
    BaseParameters m_baseParameters;
    Guid m_gRequestingUserId;
    Dictionary<string, object> m_SearchFilters;

    [DataMember]
    public  string APIKey
    {
        get { return m_baseParameters.APIKey; }
        set { m_baseParameters.APIKey = value; }
    }

    [DataMember]
    public  BaseParameters.YooshDeviceType DeviceType
    {
        get { return m_baseParameters.DeviceType; }
        set { m_baseParameters.DeviceType = value; }
    }

    [DataMember]
    public  string DeviceId
    {
        get { return m_baseParameters.DeviceId; }
        set { m_baseParameters.DeviceId = value; }
    }

    [DataMember]
    public Guid RequestingUserId
    {
        get { return m_gRequestingUserId; }
        set { m_gRequestingUserId = value; }
    }

    [DataMember]
    public Dictionary<string, object> SearchFilters
    {
       get { return m_SearchFilters; }
        set { m_SearchFilters = value; }
    }
}

Json.net 版本:6.0.8

【问题讨论】:

  • $type 是特殊的。我不认为你可以重新订购那个。这是 Newtonsoft Json 在反序列化时用来确定要创建哪个 C# 对象的方法。由于您有一个 Dictionary,它可能需要 $type 来确定要创建的对象类型。
  • 66666666-6666-6666-6666-666666666666 - 野兽的 ID

标签: c# json.net


【解决方案1】:

设置JsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead

根据documentation

此示例反序列化 JSON 并将 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
});

请注意,此设置将impact performance

最后,在使用TypeNameHandling 时,请注意Newtonsoft docs 的注意事项:

当您的应用程序从外部源反序列化 JSON 时,应谨慎使用 TypeNameHandling。使用 None 以外的值反序列化时,应使用自定义 SerializationBinder 验证传入类型。

关于为什么这可能是必要的讨论,请参阅TypeNameHandling caution in Newtonsoft Json

【讨论】:

  • 谢谢,我会在周末后测试它,但我很确定这会起作用:] 如果没有,会更新。
猜你喜欢
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
相关资源
最近更新 更多