2016-02-19 14 views
5

Ho uno scenario con una classe definita come sotto:condizionale serializzazione/deserializzazione di proprietà dell'oggetto con json.net

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

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

Quando si tenta di serializzare/deserializzare quella classe con JSON.net, esso prende il ShouldSerialize in considerazione, ma non lo ShouldDeserialize.

Secondo la documentazione, entrambi dovrebbero funzionare nello stesso modo in cui credo. C'è qualcosa di particolare che dovrei sapere? Più in generale, come devo gestire gli scenari in cui desidero serializzare una proprietà ma non deserializzarla?

Sto usando Json.NET 8.0 se questo è importante.

Grazie per il vostro aiuto.

+0

Non dice nulla su 'ShouldDeserialize' nella [documentazione] (http://www.newtonsoft.com/json/help/html/ConditionalProperties.htm). Perché dovresti serializzare qualcosa ma non deserializzare? – kjbartel

+0

@kjbartel Stesso modello per serializzazione/deserializzazione ma quando deserializza c'è un collegamento intermedio (hateoas) per accedere a quella specifica proprietà. –

+2

Vedere anche [Proprietà di serializzazione, ma non deserializzare la proprietà in Json.Net] (http: // stackoverflow.it/q/31731320/10263) –

risposta

6

La risposta breve alla tua domanda è, il controllo automatico per ShouldDeserialize{PropertyName}() non è attualmente implementato anche se ShouldSerialize{PropertyName}() è. Segue una risposta più lunga e una soluzione alternativa.

La classe JsonProperty viene utilizzata internamente da Json.NET per definire un contratto per come associare una proprietà JSON a un membro .NET o un parametro del costruttore. Dispone di due proprietà di predicato, ShouldSerialize e ShouldDeserialize che, quando non sono nulle, impediscono la serializzazione e la deserializzazione di una proprietà, rispettivamente. L'inizializzazione di ogni JsonProperty è il lavoro di ContractResolver. Per ogni proprietà {PropertyName}, il numero default contract resolver di Json.NET verifica automaticamente la presenza di un metodo public bool ShouldSerialize{PropertyName}(). Se esiste un tale metodo, aggiunge una chiamata nel predicato ShouldSerialize, sopprimendo in tal modo la serializzazione quando il metodo restituisce false. Ciò è stato implementato perché il controllo della serializzazione delle proprietà tramite un metodo ShouldSerialize{PropertyName}() è un modello standard supportato da, ad esempio, XmlSerializer. Per ulteriori informazioni sullo scenario, vedere il relativo Json.NET release notes.

Ad esempio, nella seguente classe, la serializzazione di MyObjectData sarà soppressa a meno che MyObjectData.Count > 0:

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

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

JsonProperty.ShouldDeserialize, tuttavia, non è mai impostato dal resolver contratto predefinito. Ciò potrebbe essere dovuto al fatto che non esiste un modello standard per la deserializzazione equivalente a ShouldSerialize{PropertyName}() e quindi Newtonsoft non ha mai avuto alcuna richiesta per implementare tale modello. Tuttavia, come hai notato, esiste un'infrastruttura per supportare tale modello e quindi le applicazioni possono creare custom contract resolvers che fa proprio questo. In realtà, Json.NET ha un esempio di tale resolver contratto in proprio 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; 
    } 
} 

Se si vuole sopprimere condizionalmente deserializzazione di proprietà anche se presenti in JSON, si potrebbe considerare l'utilizzo (e caching) questo risolutore di contratto.

+0

Questa è quasi la stessa della [altra risposta] (http://stackoverflow.com/a/31732029/1730559) sulla domanda duplicata. Perché non hai appena contrassegnato questa domanda come un duplicato? – kjbartel

Problemi correlati