Sjoerd222888 Sjoerd222888 - 4 months ago 14x
JSON Question

Json.Net issue with order of reference properties in JSON

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
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
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
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
property always occurs first? Is there another way than resorting the JSON string manually?

Evk Evk

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.