Newtonsoft JSON.net deserialization error, where fields in JSON change order

This is a WCF service that receives requests from Android devices. The same request works with Lollipop devices, not jelly devices, because jellybean creates JSON differently when created.

An exception:

Unexpected token when deserializing an object: String. Path 'SearchFilters.config. $ Type ', line 1, position 212.

Json does not work:

{ "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" } 

Working 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 } } ] } } } 

Some fields are in a different order. This is the only difference.

C # Class:

 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 Version: 6.0.8

+7
source share
1 answer

Set JsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead .

According to the documentation :

This example deserializes JSON with the MetadataPropertyHandling set to ReadAhead, so metadata properties should not be at the beginning of the object.

  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 }); 

Please note that this option will affect performance .

Finally, when using TypeNameHandling , pay attention to this warning from Newtonsoft docs :

TypeNameHandling should be used with caution when your application deserializes JSON from an external source. Incoming types must be checked with a special SerializationBinder when deserializing with a value other than None.

For a discussion of why this might be needed, see TypeNameHandling Caution in Newtonsoft Json .

+11
source share

All Articles