Ordering properties with class hierarchies

Apr 19, 2012 at 2:57 PM

We've found when switching to JSON.NET from the DataContractJsonSerializer that the Order parameter on [DataMember] attributes behaves differently for class hierarchies.

With .NET DataContractSerializer if the base class had order of 0,1,2 and the child class also had 0,1,2 the base class properties would be output first followed by the child properties (grouped within the class hierarchy). With JSON.NET the ordering is applied regardless of hierarchy so you'd get p0,c0,p1,c1,p2,c2.

Arguably this is better than the DataContractJsonSerializer approach but is there any way to continue this behaviour without having to resort to ranges such as child orders 100,101,102.

Coordinator
Apr 19, 2012 at 10:28 PM

No

Apr 23, 2012 at 11:06 AM

Thanks to the flexibility of JSON.NET I was able to plug-in a custom Contract Resolver to do this:

public class CustomPropertySortContractResolver : DefaultContractResolver
{
    private const int MaxPropertiesPerContract = 1000;

    protected override IList CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        List members = GetSerializableMembers(type);
        if (members == null)
        {
            throw new JsonSerializationException("Null collection of seralizable members returned.");
        }

        var properties = new JsonPropertyCollection(type);

        foreach (MemberInfo member in members)
        {
            JsonProperty property = CreateProperty(member, memberSerialization);

            if (property != null)
            {
                properties.AddProperty(property);
            }
        }

        IList orderedProperties = properties.OrderBy(p => p.Order + (MaxPropertiesPerContract * GetTypeDepth(p.DeclaringType)) ?? -1).ToList();
        return orderedProperties;
    }

    private static int GetTypeDepth(Type type)
    {
        int depth = 0;
        while ((type = type.BaseType) != null)
        {
            depth++;
        }

        return depth;
    }
}

new

JsonSerializer

{

ContractResolver =

new CustomPropertySortContractResolver()

};