2016-02-19 17 views
5

ich ein Szenario mit einer Klasse haben wie folgt definiert:Bedingte Serialisierung/Deserialisierung von Objekteigenschaften mit json.net

class MyObject 
{ 
    public DataDictionary MyObjectData { get; set; } 

    public bool ShouldSerializeMyObjectData() { return true; } 
    public bool ShouldDeserializeMyObjectData() { return false; } 
} 

Wenn ich versuche, mit JSON.net diese Klasse zu serialisiert/deserialisiert, nimmt es die ShouldSerialize berücksichtigen, aber nicht die ShouldDeserialize.

Laut der Dokumentation sollten beide auf die gleiche Weise funktionieren, denke ich. Gibt es etwas Besonderes, das ich wissen sollte? Allgemeiner: Wie sollte ich mit Szenarien umgehen, in denen ich eine Eigenschaft serialisieren, aber nicht deserialisieren möchte?

Ich verwende Json.NET 8.0, wenn das zählt.

Danke für Ihre Hilfe.

+0

Es sagt nichts über 'ShouldDeserialize' in der [Dokumentation] (http://www.newtonsoft.com/json/help/html/ConditionalProperties.htm). Warum möchten Sie etwas serialisieren, aber nicht deserialisieren? – kjbartel

+0

@ kjbartel Gleiches Modell für Serialisierung/Deserialisierung, aber beim Deserialisieren gibt es eine Intermediary-Verknüpfung (hateas) für den Zugriff auf diese spezifische Eigenschaft. –

+2

Siehe auch [Serialize-Eigenschaft, aber Deserialize-Eigenschaft in Json.Net nicht] (http: // stackoverflow.com/q/31731320/10263) –

Antwort

6

Die kurze Antwort auf Ihre Frage ist, automatisch für ShouldDeserialize{PropertyName}() Überprüfung derzeit nicht einmal implementiert, obwohl ShouldSerialize{PropertyName}() ist. Eine längere Antwort und Workaround folgen.

Die Klasse JsonProperty wird intern von Json.NET verwendet, um einen Vertrag zu definieren, wie ein JSON-Objekt in eine .NET-Mitglied oder Konstruktorparameter abzubilden. Es hat zwei Prädikateigenschaften, ShouldSerialize und ShouldDeserialize, die, wenn sie nicht null sind, verhindern, dass eine Eigenschaft serialisiert bzw. deserialisiert wird. Das Initialisieren jedes JsonProperty ist die Aufgabe des ContractResolver. Für jede Eigenschaft {PropertyName} prüft Json.NET default contract resolver automatisch auf das Vorhandensein einer public bool ShouldSerialize{PropertyName}() Methode. Wenn eine solche Methode vorhanden ist, fügt sie im Prädikat ShouldSerialize einen Aufruf hinzu, wodurch die Serialisierung unterdrückt wird, wenn die Methode false zurückgibt. Dies wurde implementiert, da das Steuern der Eigenschaftserialisierung über ein Verfahren ShouldSerialize{PropertyName}() ein Standardmuster ist, das beispielsweise von XmlSerializer unterstützt wird. Für mehr Hintergrund siehe die relevanten Json.NET release notes.

Zum Beispiel in der folgenden Klasse, Serialisierung von MyObjectData wird, es sei denn MyObjectData.Count > 0 unterdrückt werden:

class MyObject 
{ 
    public DataDictionary MyObjectData { get; set; } 

    public bool ShouldSerializeMyObjectData() { return MyObjectData != null && MyObjectData.Count > 0; } 
} 

JsonProperty.ShouldDeserialize jedoch es wird nie durch den Standardvertrag Resolver gesetzt. Dies kann darauf zurückzuführen sein, dass es kein Standardmuster für die Deserialisierung gibt, das ShouldSerialize{PropertyName}() entspricht, und daher hatte Newtonsoft niemals Anforderungen, ein solches Muster zu implementieren. Wie Sie jedoch bemerkt haben, existiert eine Infrastruktur zur Unterstützung eines solchen Musters, und so können Anwendungen custom contract resolvers erstellen, die genau das tun. In der Tat hat Json.NET ein Beispiel eines solchen Vertrags Resolver in seinem eigenen test suite:

public class ShouldDeserializeContractResolver : DefaultContractResolver 
{ 
    public static new readonly ShouldDeserializeContractResolver Instance = new ShouldDeserializeContractResolver(); 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 

     MethodInfo shouldDeserializeMethodInfo = member.DeclaringType.GetMethod("ShouldDeserialize" + member.Name); 

     if (shouldDeserializeMethodInfo != null) 
     { 
      property.ShouldDeserialize = o => { return (bool)shouldDeserializeMethodInfo.Invoke(o, null); }; 
     } 

     return property; 
    } 
} 

public class ShouldDeserializeTestClass 
{ 
    [JsonExtensionData] 
    public IDictionary<string, JToken> ExtensionData { get; set; } 

    public bool HasName { get; set; } 
    public string Name { get; set; } 

    public bool ShouldDeserializeName() 
    { 
     return HasName; 
    } 
} 

Wenn Sie bedingt wollen Deserialisierung von Eigenschaften unterdrücken, selbst wenn in der JSON, könnten Sie in Betracht ziehen (und caching) dieser Vertragsresolver.

+0

Dies ist fast das gleiche wie Ihre [andere Antwort] (http://stackoverflow.com/a/31732029/1730559) auf die doppelte Frage. Warum hast du diese Frage nicht einfach als Duplikat markiert? – kjbartel