2016-10-17 2 views
1

Ich habe eine Modellklasse deklariert, deren Eigenschaften von JSON aufgefüllt werden müssen, und einige, die mit Code gefüllt werden, angezeigt durch die Attribute JsonObject und . Hier ist eine vereinfachte Version:Unerwartete Json.NET-Ausnahme bei Verwendung von MemberSerialization.OptIn und Required.Always

[JsonObject(MemberSerialization.OptIn, ItemRequired = Required.Always)] 
public class AppCard 
{ 
    [JsonProperty] 
    public string Name { get; set; } 

    [JsonProperty] 
    public string Author { get; set; } 

    public bool IsInstalled { get; set; } 
} 

Hier ist die JSON aus meinem Unit-Test:

[ 
    { 
    "name": "App 1", 
    "author": "Author 1" 
    }, 
    { 
    "name": "App 2", 
    "author": "Author 2" 
    } 
] 

Und hier ist, wo ich DeserializeObject nennen:

appCards = JsonConvert.DeserializeObject<IEnumerable<AppCard>>(content); 

Leider ist dies nicht mit der Folgefehler:

Newtonsoft.Json.JsonSerializationException: Required property 'IsInstalled' 
not found in JSON. Path '[0]', line 5, position 3. 

Da diese Eigenschaft nicht über das JsonProperty-Attribut verfügt und OptIn angegeben wird, ging ich davon aus, dass die DeserializeObject-Methode sie ignorieren würde. Habe ich missverstanden, wie diese Einstellungen zusammen funktionieren sollen?

Antwort

2

Das fühlt sich wie ein Fehler für mich an. Beim Durchlaufen des Codes markiert Json.Net ungeschmückte Eigenschaften als ignoriert, wenn MemberSerialization auf OptIn festgelegt ist, berücksichtigt jedoch nicht den ignorierten Status, wenn die erforderlichen Eigenschaften überprüft werden. Das gleiche passiert, wenn Sie OptOut Serialisierung (Standardeinstellung) verwenden, markieren Sie das Objekt nach Bedarf Eigenschaften und markieren Sie dann explizit eine Eigenschaft mit [JsonIgnore]:

[JsonObject(ItemRequired = Required.Always)] 
public class AppCard 
{ 
    public string Name { get; set; } 

    public string Author { get; set; } 

    [JsonIgnore] 
    public bool IsInstalled { get; set; } 
} 

Es ist möglich, dies durch Design, aber es scheint zu verletzen "Prinzip der geringsten Überraschung". Vielleicht möchten Sie report an issue.

Um dieses Problem zu umgehen, markieren Sie die einzelnen Eigenschaften einfach über das Attribut [JsonProperty], anstatt diese Option für die Klasse festzulegen. Da Sie bereits alle Ihre Eigenschaften mit [JsonProperty] markiert haben (aufgrund der Verwendung von OptIn), sollte es einfach sein, die Option Required mit find and replace hinzuzufügen.

[JsonObject(MemberSerialization.OptIn)] 
public class AppCard 
{ 
    [JsonProperty(Required = Required.Always)] 
    public string Name { get; set; } 

    [JsonProperty(Required = Required.Always)] 
    public string Author { get; set; } 

    public bool IsInstalled { get; set; } 
} 
+0

Ich dachte, es könnte ein Fehler sein (oder schließen) - danke fürs Durchgraben und Bestätigen! Und danke für die Problemumgehung - es ist sehr sauber, wie du gesagt hast. –

0

Sie angeben, dass ItemRequired = Required.Always,

in der Dokumentation nach:

Gets or sets a value that indicates whether the object's properties are required.

Und Ihr IsInstalled Mitglied ist effektiv eine Eigenschaft.

Einige Optionen in JsonObject schließen sich gegenseitig aus, obwohl not explicitly stated.

+0

Warum sollte DeserializeObject IsInstalled als erforderliche Eigenschaft behandeln, wenn es explizit von der Serialisierung ausgeschlossen wird? –

+0

Nun, wir können es nicht sicher sagen, es sei denn, man schaut sich die Quelle an, aber ich würde sagen, 'ItemRequired' hat Vorrang vor' MemberSerialization.OptIn'. – Aybe

Verwandte Themen