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
Try/Catch + Using, Right Syntax
Read and Write File on Streamingassetspath
Invoke C# Code from JavaScript in a Document in a Webbrowser
C# Equivalent to Java's Charat()
How to Access Winform Textbox Control from Another Class
Converting a String to a Class Name
Loading Dlls into a Separate Appdomain
Read Fixed Width Record from Text File
How to Detect If a Property Exists on an Expandoobject
How to Filter Directory.Enumeratefiles with Multiple Criteria
How to Reference Embedded Images from CSS
Adding Distance to a Gps Coordinate
Handling Decimal Values in Newtonsoft.JSON
Does Java Have Something Similar to C# Properties