Reihenfolge der Felder beim Serialisieren der abgeleiteten Klasse in JSON.NET

Reihenfolge der Felder beim Serialisieren der abgeleiteten Klasse in JSON.NET

Nur als Ergänzung verwendet ein anderer Ansatz als die akzeptierte Antwort [JsonProperty(Order = -2)]; Sie können Ihre Basisklasse wie folgt ändern:

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

Der Grund für das Festlegen von Bestellwerten auf -2 ist, dass jede Eigenschaft ohne expliziten Bestellwert standardmäßig einen Wert von -1 hat. Sie müssen also entweder allen untergeordneten Eigenschaften einen Order-Wert zuweisen oder die Eigenschaften Ihrer Basisklasse einfach auf -2 setzen.


Gemäß dem JSON-Standard ist ein JSON-Objekt ein ungeordneter Satz von Name/Wert-Paaren . Meine Empfehlung wäre also, sich keine Gedanken über die Eigentumsordnung zu machen. Trotzdem können Sie die gewünschte Reihenfolge erhalten, indem Sie Ihre eigene ContractResolver erstellen von einem der Standardvertragslöser erben und dann CreateProperties überschreiben :

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

Und dann verwenden Sie es wie folgt:

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

Hinweise:

  • Dieser Ansatz funktioniert besonders gut bei Typhierarchien mit mehreren Ebenen, da er die korrekte Reihenfolge von Eigenschaften aus allen Ebenen in der Hierarchie automatisiert.

  • Newtonsoft empfiehlt, Instanzen von Contract-Resolvern für eine optimale Leistung zwischenzuspeichern.

Demo-Geige hier.


Wenn Sie ASP.NET Core verwenden, überschreiben Sie keine wichtigen Vertragsauflösungseinstellungen, die standardmäßig bereitgestellt werden. Nach der Antwort von @dbc können Sie Folgendes tun:

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