Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Consider these two classes:

public Class Base {     public string Id {get; set;}     public string Name {get; set;}     public string LastName {get; set;} } 

And the derived class:

public Class Derived : Base {     public string Address {get; set;}     public DateTime DateOfBirth {get; set;} } 

When serializing the Derived class using Json.Net:

Derived record = new Derived record(); {// Initialize here...} JsonConvert.SerializeObject(record); 

By default, the properties of the Derived class appear first:

{    "address": "test",    "date_of_birth" : "10/10/10",   "id" : 007,   "name" : "test name",   "last_name": "test last name"  } 

What I need:

{    "id" : 007,   "name" : "test name",   "last_name": "test last name"   "address": "test",    "date_of_birth" : "10/10/10",        } 

Question

Is it possible to have the base class properties come first, when serializing the derived class (without using [JsonProperty(Order=)] for each property of both classes)?

like image 290
A-Sharabiani Avatar asked Sep 14 '15 18:09

A-Sharabiani


People also ask

Are JSON properties Order?

The attributes mentioned in the annotation are first serialized to JSON in the order defined, followed by other properties in the class.

What is serializing in JSON?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).

Which of the following options represent the class used to perform JSON serialization in net?

We can implement JSON Serialization/Deserialization in the following three ways: Using JavaScriptSerializer class. Using DataContractJsonSerializer class. Using JSON.NET library.


2 Answers

Just as a complement, another approach different than the accepted answer is using [JsonProperty(Order = -2)]; You can modify your base class as follow:

public class Base {     [JsonProperty(Order = -2)]     public string Id { get; set; }      [JsonProperty(Order = -2)]     public string Name { get; set; }      [JsonProperty(Order = -2)]     public string LastName { get; set; } } 

The reason of setting Order values to -2 is that every property without an explicit Order value has a value of -1 by default. So you need to either give all child properties an Order value, or just set your base class' properties to -2.

like image 178
Moshtaf Avatar answered Oct 10 '22 06:10

Moshtaf


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.

like image 21
dbc Avatar answered Oct 10 '22 08:10

dbc