JSON.net sollte keine Standardwerte für Konstruktorparameter verwenden, sollte Standard für Eigenschaften verwenden [geschlossen]

8

Gibt es eine Möglichkeit, JSON.net mitzuteilen, dass es, wenn es versucht, mit einem Konstruktor zu deserialisieren (wenn es keinen Standardkonstruktor gibt), den Konstruktorparametern keinen Standardwert zuweisen sollte und dass es nur einen Konstruktor aufrufen sollte Konstruktorparameter wird in der JSON-Zeichenfolge dargestellt? Derselbe Serializer SOLL Standardwerte beim Aufruf von Property / Field Settern verwenden, die Regel ist nur auf Konstruktoren beschränkt. Keiner der Enum-Werte hier scheint angemessen zu sein: Ссылка

Die Lösung sollte sich NICHT darauf verlassen, Attribute auf die zu deserialisierenden Typen anzuwenden.

Beispielsweise wird die JSON-Zeichenfolge "{}" zu einem Objekt vom Typ Dog deserialisiert, indem das Alter des Hunds auf 0 gesetzt wird (der Standardwert für ein int). Ich möchte eine verallgemeinerte, nicht attributbasierte Lösung, um dies zu verhindern. In diesem Fall würde {"age":4} funktionieren, weil age in der JSON-Zeichenfolge angegeben ist und dem Konstruktorparameter entspricht.

%Vor%

Wenn jedoch Dog als solches angegeben wird, sollte "{}" auf einen Hund mit Age == 0 deserialisiert werden, da der Hund nicht mit einem Konstruktor erstellt wird.

> %Vor%

Und um irgendwelche Fragen über "warum sollten Sie dies tun wollen" zu vermeiden ... Objekte mit Konstruktoren sind in der Regel qualitativ anders als POCOs, was ihre Eigenschaften betrifft. Die Verwendung eines Konstruktors zum Speichern von Eigenschaftswerten anstelle von einstellbaren Eigenschaften in einem POCO bedeutet in der Regel, dass Sie die Eigenschaftswerte validieren / einschränken möchten. Daher ist es sinnvoll, die Deserialisierung mit Standardwerten bei Vorhandensein von Konstruktoren nicht zuzulassen.

    
SFun28 24.05.2016, 14:14
quelle

1 Antwort

3

Wenn Json.NET ein Objekt ohne einen parameterlosen Konstruktor, aber mit einem parametrisierten Konstruktor findet, ruft es diesen Konstruktor auf, um das Objekt Anpassen der JSON-Eigenschaftsnamen an die Konstruktorargumente anhand des Namens mithilfe von Reflektion über einen Algorithmus ohne Berücksichtigung der Groß- und Kleinschreibung. I.e. Eine Eigenschaft, deren Name auch im Konstruktor erscheint, wird über den Konstruktoraufruf gesetzt, nicht über die set-Methode (selbst wenn es eine gibt).

Somit können Sie ein Konstruktorargument nach Bedarf markieren, indem Sie die entsprechende Eigenschaft als erforderlich markieren :

%Vor%

Jetzt wird JsonConvert.DeserializeObject<Dog>(jsonString) ausgeben, wenn die Eigenschaft "age" fehlt.

Da Sie immer möchten, können Sie einen benutzerdefinierten Vertrag erstellen Resolver , das von DefaultContractResolver oder CamelCasePropertyNamesContractResolver , das Eigenschaften, die an den Konstruktor übergeben werden, automatisch als erforderlich kennzeichnet, ohne dass Attribute benötigt werden:

%Vor%

Dann

%Vor%

Wird noch einmal werfen.

(Beachten Sie, dass dies nur funktioniert, wenn eine entsprechende Eigenschaft ist. Es scheint keine direkte Möglichkeit zu sein, einen Konstruktorparameter mit keiner entsprechenden Eigenschaft wie erforderlich zu markieren.)

    
dbc 24.05.2016, 18:45
quelle

Tags und Links