2014-12-17 20 views
5

Mam klasę, która jest opatrzona przypisami atrybutów DataContract i DataMember. Niektórzy członkowie są oznaczeni jako DataMember(IsRequired = true). Kiedy serializuję instancje za pośrednictwem drutu z Json.NET, a wymagane elementy obiektu mają wartość null, to ich wartości szeregowane są nieobecne na wyjściu (co najwyraźniej jest równoważne byciu wartością null w JSON). Nie przeszkadza mi to.Jak deserializować brakującą właściwość do wartości domyślnej w Json.NET?

Utworzono rodzaj usługi "echo", która zwraca dane wysłane do niej jako odpowiedź. Tak więc ta usługa odbiera JSON z brakującymi elementami członkowskimi (lub zerowymi członkami w zależności od tego, jak na to patrzysz), a następnie przesyła je z powrotem do mojego klienta Json.NET. JSON na drucie wygląda tak samo w obu kierunkach, jak widziany przez Fiddlera (sniffer proxy). Jak na razie dobrze.

Gdy oryginał Json.NET nadawca otrzyma odpowiedź JSON, żeby go deserializowania The serializer zgłasza wyjątek o nie znalezieniu wymaganych członków w danych JSON:

Required property 'IAmRequired' not found in JSON. Path ''. 

To niefortunne, ponieważ serializer jest zatem nie może deserializować danych, które wcześniej serializował bez problemu.

Brak zmiany klasy DataContract, aby członek nie był wymagany (czego nie chcę robić z wielu powodów), czy istnieje sposób, aby Json.NET zendrializować brakujące elementy do wartości domyślnych, takich jak null?

Oto mój kod deserializacji:

HasRequired h = null; 
JObject json = response as JObject; // hand waving here 
try 
{ 
    JsonSerializer ser = new JsonSerializer(); 
    ser.MissingMemberHandling = MissingMemberHandling.Ignore; // doesn't seem to help 
    ser.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate; // doesn't seem to help 
    ser.NullValueHandling = NullValueHandling.Include; // doesn't seem to help 
    h = json.ToObject<HasRequired>(ser); 
} 
catch (Exception ex) 
{ 
    // bummer, missing required members still 
} 
+0

czekaj, więc trzeba członkowie oznaczone jako wymagane, ale oni naprawdę nie są wymagane? –

+0

Są one wymagane ... ale tylko po to, aby spełnić pewne obstrukcyjne reguły dla DataContractSerializer, aby móc obsłużyć serializację dla WCF (dla powiązania SOAP) i nie mieć tego typu wyglądu dla klientów. Wiem co mówisz; gdyby nie serializator DC, byłyby opcjonalne. W przypadku końca serializacji SOAP, którego starałem się unikać, obiekty są serializowane jako instancje zerowe XML (są jawnie wysyłane jako puste). – Greg

+0

Rozumiem. Dodałem odpowiedź, która powinna ci pomóc. –

Odpowiedz

0

To wygląda jak prawdziwy brodawki na moim kodu i należy powtórzyć dla każdego członka wartości pustych-ale-to wymagane, ale to działa, i wydaje się, aby dodać pomijalne nad głową. Dodałem to tuż przed blokiem try w moim oryginalnym fragmencie:

JToken maybeHasIt = null; 
if (!json.TryGetValue("IAmRequired", StringComparison.InvariantCultureIgnoreCase, out maybeHasIt)) 
{ 
    json.Add("IAmRequired", null); 
} 
3

Jeśli mają właściwości oznaczonych [DataMember(Required = true)] i chcesz nadpisać wymagane zachowanie, istnieje kilka rzeczy, które możesz zrobić:

  1. Możesz oznaczyć te same właściwości za pomocą [JsonProperty(Required = Required.Default)]. Działa to, ponieważ [JsonProperty] ma pierwszeństwo przed [DataMember] w Json.Net.

    [DataContract] 
    public class HasRequired 
    { 
        [DataMember(Required = true)] 
        [JsonProperty(Required = Required.Default)] 
        public string IAmRequired { get; set; } 
    } 
    
  2. Lub można utworzyć niestandardową ContractResolver że programowo ustawia Required = Required.Default na każdym obiekcie.

    class CustomResolver : DefaultContractResolver 
    { 
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
        { 
         JsonProperty prop = base.CreateProperty(member, memberSerialization); 
         prop.Required = Required.Default; 
         return prop; 
        } 
    } 
    

    Aby skorzystać z rozpoznawania nazw, po prostu ustawić właściwość ContractResolver na serializatora do nowej instancji niestandardowych rezolwerem:

    JsonSerializer ser = new JsonSerializer(); 
    ser = new CustomResolver(); 
    
Powiązane problemy