Order of Serialized Fields Using JSON.Net

Order of serialized fields using JSON.NET

The supported way is to use the JsonProperty attribute on the class properties that you want to set the order for. Read the JsonPropertyAttribute order documentation for more information.

Pass the JsonProperty an Order value and the serializer will take care of the rest.

 [JsonProperty(Order = 1)]

This is very similar to the

 DataMember(Order = 1) 

of the System.Runtime.Serialization days.

Here is an important note from @kevin-babcock

... setting the order to 1 will only work if you set an order greater than 1 on all other properties. By default any property without an Order setting will be given an order of -1. So you must either give all serialized properties and order, or set your first item to -2

Order of fields when serializing the derived class in JSON.NET

According to the JSON standard, a JSON object is an unordered set of name/value pairs. So my recommendation would be to not worry about property order. Nevertheless you can get the order you want by creating your own ContractResolver inheriting from one of the standard contract resolvers, and then overriding CreateProperties:

public class BaseFirstContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) =>
base.CreateProperties(type, memberSerialization)
?.OrderBy(p => p.DeclaringType.BaseTypesAndSelf().Count()).ToList();
}

public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}

And then use it like:

// Cache an instance of the resolver for performance
static IContractResolver baseFirstResolver = new BaseFirstContractResolver { /* Set any required properties here e.g. NamingStrategy = new CamelCaseNamingStrategy() */ };

// And use the cached instance when serializing and deserializing
var settings = new JsonSerializerSettings
{
ContractResolver = baseFirstResolver,
// Add your other settings here.
TypeNameHandling = TypeNameHandling.Objects
};
var json = JsonConvert.SerializeObject(derived, typeof(Base), Formatting.Indented, settings);

Notes:

  • This approach works especially well with multi-level type hierarchies as it automates correct ordering of properties from all levels in the hierarchy.

  • Newtonsoft recommends caching instances of contract resolvers for best performance.

Demo fiddle here.

JsonConvert.SerializeObject changes the sort order of fields in JSON

It turns out that JsonConvert.SerializeObject doesn't guarantee the default order of fields. To specify an explicit sorting, you can use the DefaultContractResolver

Thanks Andy for the idea!

Implementation of custom DefaultContractResolver:

 public class OrderedContractResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return base.CreateProperties(type, memberSerialization).OrderBy(p=>p.PropertyName).ToList();
}
}

Usage example:

 var jsonSerializerSettings = new JsonSerializerSettings  {ContractResolver = new OrderedContractResolver()};

var str = JsonConvert.SerializeObject(token, jsonSerializerSettings);

.NET core 3: Order of serialization for JsonPropertyName (System.Text.Json.Serialization)

It's supported in .Net 6 and greater using JsonPropertyOrderAttribute:

JsonPropertyOrderAttribute Class

Specifies the property order that is present in the JSON when serializing. Lower values are serialized first. If the attribute is not specified, the default value is 0.

If multiple properties have the same value, the ordering is undefined between them.

The attribute can be applied e.g. as follows:

[JsonPropertyOrder(order : 1)]

Set the order of JSON properties serialized from a third-party object

Although the JSON spec technically defines an object as "an unordered set of name/value pairs", JSON.net will still allow you to set the order of the properties if you want. In your resolver, you just need to set the Order values on each JsonProperty and then return them sorted accordingly.

protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization)
.Where(p => _propertiesToSerialize.Contains(p.PropertyName)).ToList();

foreach (JsonProperty prop in properties)
{
prop.Order = _propertiesToSerialize.IndexOf(prop.PropertyName) + 1;
}

return properties.OrderBy(p => p.Order).ToList();
}

Working demo: https://dotnetfiddle.net/OhfWHl

How to sort serialized fields using System.Text.Json

After reading the thread stackoverflow.com/questions/3330989 indicated by @AlexeiLevenkov. I realized that It is easier using NewtonSoft.Json. So I set the attribute [JsonProperty(Order = -2)] to "ID" property and exchange System.Text.Json.JsonSerializer.Serialize(student) for JsonConvert.SerializeObject(student); It worked properly!

Below is the code updated.

class Program
{
static void Main(string[] args)
{
Student student = new Student()
{
Name = "Robert",
Id = Guid.NewGuid(),
LastName = "Alv",
Check = "Ok"
};

var resultJson = JsonConvert.SerializeObject(student);
Console.WriteLine(resultJson);
Console.ReadLine();

}
class BaseClass1
{
[JsonProperty(Order = -2)]
public Guid Id { get; set; }
}

class BaseClass2 : BaseClass1
{

}

class People : BaseClass2
{
public string Name { get; set; }
public string LastName { get; set; }
public string Check { get; set; }
}

class Student : BaseClass2
{
public string Name { get; set; }
public string LastName { get; set; }
public string Check { get; set; }
}
}

Is array order preserved when deserializing using json.net?

It depends on what collection you're using.

Any class implementing IEnumerable/IEnumerable<T> can be serialized as a JSON array. Json.NET processes collection sequentally, that is, it will serialize array items in the order the collection returns them from GetEnumerator and will add items to the collection in the order they're deserialized from JSON file (using either Add method in case of mutable collections, and constructor with collection argument in case of immutable collections).

That means that if the collection preserves the order of items (T[], List<T>, Collection<T>, ReadOnlyCollection<T> etc.), the order will be preserved when serializing and deserializing. However, if a collection doesn't preserve the order of items (HashSet<T> etc.), the order will be lost.

The same logic applies to JSON objects. For example, the order will be lost when serializing Dictionary<TKey, TValue>, because this collection doesn't preserve the order of items.

Order of properties get messed up when serialized by JSON.NET

1.) No, order doesn't matter.

2.) You can use the [JsonProperty(Order=x)] attribute to control the order:

public class Employee : Person
{
[JsonProperty(Order = 1)]
public int DepartmentId { get; set; }

[JsonProperty(Order = 1)]
public string Title { get; set; }
}

From a quick test, order defaults to 0, is sorted from low to high, and properties with the same value of Order are sorted in an arbitrary order.



Related Topics



Leave a reply



Submit