Reputation: 3476
The order of properties is not defined so I would expect the order of the properties in JSON also not to be defined. However I find Newtonsoft.Json to expect a certain order when having references (I am using PreserveReferencesHandling = PreserveReferencesHandling.All
). It expects the $id
property to be the first occurring property in JSON.
I have come to this conclusion with the following test
string cyclicJson1 = "{\"FirstChild\":{\"OtherChild\":{\"OtherChild\":{\"$ref\":\"1\"},\"Parent\":{\"$ref\":\"0\"},\"$id\":\"2\"},\"Parent\":{\"$ref\":\"0\"},\"$id\":\"1\"},\"SecondChild\":{\"$ref\":\"2\"},\"$id\":\"0\"}\"";
cannot be deserilized correctly (some reference are null
which should not) by Newtonsoft.Json where as the following can:
string cyclicJson2 = "{\"$id\": \"0\",\"FirstChild\": {\"$id\": \"1\",\"OtherChild\": {\"$id\": \"2\",\"OtherChild\": {\"$ref\": \"1\"},\"Parent\": {\"$ref\": \"0\"}},\"Parent\": {\"$ref\": \"0\"},},\"SecondChild\": {\"$ref\": \"2\"}}";
The only difference being that I manually moved the $id
property forward such that it is the first element for each object.
The classes are defined as follows:
class CycleTestParent
{
public CycleTestChild FirstChild { get; set; }
public CycleTestChild SecondChild { get; set; }
public CycleTestParent()
{
FirstChild = new CycleTestChild();
SecondChild = new CycleTestChild();
}
}
private class CycleTestChild
{
public CycleTestParent Parent { get; set; }
public CycleTestChild OtherChild { get; set; }
}
Is there a way that I can work with Newtonsoft.Json without having to assume that the $id
property always occurs first? Is there another way than resorting the JSON string manually?
Upvotes: 1
Views: 108
Reputation: 101493
What you need here is to set MetadataPropertyHandling
to MetadataPropertyHandling.ReadAhead
:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
};
By default, for perfomance reasons, metadata properties are expected to be located at the beginning of object JSON. With this property you can change parser behaviour to look them in any place inside object JSON.
Upvotes: 1