Orden de campos al serializar la clase derivada en JSON.NET

Orden de campos al serializar la clase derivada en JSON.NET

Solo como complemento, otro enfoque diferente a la respuesta aceptada es usar [JsonProperty(Order = -2)]; Puede modificar su clase base de la siguiente manera:

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; }
}

La razón de establecer los valores de Orden en -2 es que cada propiedad sin un valor de Orden explícito tiene un valor de -1 por defecto. Por lo tanto, debe otorgar a todas las propiedades secundarias un valor de pedido o simplemente establecer las propiedades de su clase base en -2.


De acuerdo con el estándar JSON, un objeto JSON es un conjunto desordenado de pares de nombre/valor . Entonces mi recomendación sería no preocuparse por el orden de la propiedad. No obstante, puede obtener el pedido que desee creando su propio ContractResolver heredando de uno de los solucionadores de contratos estándar y luego anulando 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;
        }
    }
}

Y luego úsalo como:

// 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);

Notas:

  • Este enfoque funciona especialmente bien con jerarquías de tipos de varios niveles, ya que automatiza el orden correcto de las propiedades de todos los niveles de la jerarquía.

  • Newtonsoft recomienda almacenar en caché instancias de resolución de contratos para obtener el mejor rendimiento.

Violín de demostración aquí.


Si usa ASP.NET Core, no anule la configuración importante de resolución de contratos proporcionada de forma predeterminada. Siguiendo la respuesta de @dbc, puede hacer esto:

class DataContractJsonResolver : DefaultContractResolver
{
    public DataContractJsonResolver()
    {
        NamingStrategy = new CamelCaseNamingStrategy();
    }

    protected override IList<JsonProperty> CreateProperties( Type type, MemberSerialization memberSerialization )
    {
        return base.CreateProperties( type, memberSerialization )
            .OrderBy( p => BaseTypesAndSelf( p.DeclaringType ).Count() ).ToList();

        IEnumerable<Type> BaseTypesAndSelf( Type t )
        {
            while ( t != null ) {
                yield return t;
                t = t.BaseType;
            }
        }
    }
}