2016-02-19 11 views
5

Mam scenariusz z grupy zdefiniowane jak poniżej:warunkowego serializacji/deserializacji właściwości obiektu z Json.NET

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

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

Przy próbie serializacji/deserializowania tej klasy z Json.NET, przybiera ShouldSerialize pod uwagę, ale nie pod kątem ShouldDeserialize.

Zgodnie z dokumentacją obie powinny działać w ten sam sposób, jak sądzę. Czy jest coś szczególnego, co powinienem wiedzieć? Mówiąc bardziej ogólnie, jak mam sobie radzić ze scenariuszami, w których chcę serializować właściwość, ale jej nie deserializować?

Używam Json.NET 8.0, jeśli to ma znaczenie.

Dzięki za pomoc.

+0

Nie mówi nic o 'ShouldDeserialize' w [documentation] (http://www.newtonsoft.com/json/help/html/ConditionalProperties.htm). Dlaczego chcesz serializować coś, ale nie deserializować go? – kjbartel

+0

@kjbartel Ten sam model do serializacji/deserializacji, ale przy deserializacji istnieje link intermediarly (hateoas) do uzyskiwania dostępu do tej konkretnej właściwości. –

+2

Zobacz także [Serialize Property, ale nie Deserialize Property w Json.Net] (http: // stackoverflow.com/q/31731320/10263) –

Odpowiedz

6

Krótka odpowiedź na to pytanie to: automatyczne sprawdzenie pod kątem numeru ShouldDeserialize{PropertyName}() nie jest obecnie zaimplementowane, mimo że jest to ShouldSerialize{PropertyName}(). Dłuższą odpowiedź i obejście tego problemu.

Klasa jest używana wewnętrznie przez Json.NET do zdefiniowania umowy dotyczącej mapowania właściwości JSON na składnik .NET lub parametr konstruktora. Ma dwie właściwości predykatu: ShouldSerialize i ShouldDeserialize, które, gdy nie są zerowe, uniemożliwiają odpowiednio serializację i deserializację właściwości. Inicjowanie każdego JsonProperty jest zadaniem urządzenia ContractResolver. Dla każdej właściwości {PropertyName} Json.NET-a default contract resolver automatycznie sprawdza obecność metody public bool ShouldSerialize{PropertyName}(). Jeśli taka metoda istnieje, dodaje do niej wywołanie w predykacie ShouldSerialize, tym samym tłumiąc serializację, gdy metoda zwraca false. Zostało to zaimplementowane, ponieważ kontrolowanie serializacji właściwości za pomocą metody ShouldSerialize{PropertyName}() jest standardowym wzorcem obsługiwanym np. Przez XmlSerializer. Aby uzyskać więcej informacji, zapoznaj się z odpowiednią wersją Json.NET release notes.

Na przykład w poniższej klasie serializacji MyObjectData będą tłumione chyba MyObjectData.Count > 0:

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

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

JsonProperty.ShouldDeserialize jednak to nigdy nie jest ustawiony przez domyślną zamówienia rezolwerem. Może to wynikać z faktu, że nie ma standardowego wzorca do deserializacji równoważnego ShouldSerialize{PropertyName}(), a więc Newtonsoft nigdy nie miał żadnych żądań wprowadzenia takiego wzoru. Niemniej jednak, jak już zauważyłeś, infrastruktura obsługująca taki wzorzec istnieje, a więc aplikacje mogą tworzyć custom contract resolvers, które właśnie to robią. W rzeczywistości, Json.NET ma przykład takiego rezolwerem kontraktu w swoim własnym 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; 
    } 
} 

Jeśli chcesz warunkowo tłumić deserializacji właściwości nawet gdy są obecne w JSON, można rozważyć użycie (a caching) ten resolver umowy.

+0

To jest prawie taka sama jak twoja [inna odpowiedź] (http://stackoverflow.com/a/31732029/1730559) na duplikacie pytania. Dlaczego po prostu nie oznaczyłeś tego pytania jako duplikatu? – kjbartel

Powiązane problemy