This is a WCF service getting requests from android devices. Same request works from Lollipop devices, not from jellybean devices, because jellybean arranges the JSON differently on creation.
The exception:
Unexpected token when deserializing object: String. Path 'SearchFilters.config.$type', line 1, position 212.
Non working 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"
}
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.. Thats the only difference.
The 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
Set JsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
.
According to the documentation:
This sample deserializes JSON with MetadataPropertyHandling set to ReadAhead so that metadata properties do not need to be at the start of an 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 });
Note that this setting will impact performance.
Finally, when using TypeNameHandling
, do take note of this caution from the Newtonsoft docs:
TypeNameHandling should be used with caution when your application deserializes JSON from an external source. Incoming types should be validated with a custom SerializationBinder when deserializing with a value other than None.
For a discussion of why this may be necessary, see TypeNameHandling caution in Newtonsoft Json.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With