I'm using json.net to store a serialised object that I would like people to be able to edit in a text editor. I have a base class that contains the name of the object and then a class that inherits from that and adds some other properties.
The problem is that the the properties are written out such that the derived classes properties are written first, and then the base class afetr, so I get:
{
"MySpecialFiled": 4,
"Name": "This Is My Object",
"AnotherBaseField": 8,
}
rather than:
{
"Name": "This Is My Object",
"AnotherBaseField": 8,
"MySpecialFiled": 4,
}
You can see how this get's a bit of a pain when you have a bunch of fields in the derived class and want to actually view/edit in a text editor!
I've messed around with the source code particularly:
public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)
and
public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
in ReflectionUtils.cs, to try and reverse the order so that base class properties come first, but I've not had any success yet. Am I missing something trivial?
I don't think you need to change JSON.Net's code to do it. Apparently you can do it with a custom contract resolver - by inheriting from DefaultContractResolver - as shown in this code pasted by someone with a similar issue on the json.net forum. That poster overrides CreateProperties
and sorts the properties by how deeply inherited the defining type is.
The following code is based on code from that post (by LittleColin on CodePlex). This compiles but isn't tested:
public class CustomPropertySortContractResolver : DefaultContractResolver
{
private const int MaxPropertiesPerContract = 1000;
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var members = GetSerializableMembers(type);
if (members == null)
{
throw new JsonSerializationException("Null collection of serializable members returned.");
}
return members.Select(member => CreateProperty(member, memberSerialization))
.Where(x => x != null)
.OrderBy(p => (p.Order
+ (MaxPropertiesPerContract * GetTypeDepth(p.DeclaringType)))
?? -1)
.ToList();
}
private static int GetTypeDepth(Type type)
{
int depth = 0;
while ((type = type.BaseType) != null)
{
depth++;
}
return depth;
}
}
See also this project for similar code that filters the properties to be serialized.
Just to complement, I have suggested another approach different than accepted answer using [JsonProperty(Order = -2)]
here:
Order of fields when serializing the derived class in JSON.NET
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