Ich habe eine Klasse mit einem Standardkonstruktor und einem überladenen Konstruktor, der eine Reihe von Parametern akzeptiert. Diese Parameter stimmen mit Feldern im Objekt überein und werden bei der Erstellung zugewiesen. An diesem Punkt brauche ich den Standardkonstruktor für andere Zwecke, also möchte ich ihn behalten, wenn ich kann.
Mein Problem: Wenn ich den Standardkonstruktor entferne und die JSON-Zeichenfolge übergebe, deserialisiert das Objekt korrekt und übergibt die Konstruktorparameter ohne Probleme. Am Ende bekomme ich das Objekt so zurück, wie ich es erwartet hätte. Sobald ich jedoch den Standardkonstruktor zum Objekt hinzufüge, werden beim Aufrufen JsonConvert.DeserializeObject<Result>(jsontext)
die Eigenschaften nicht mehr ausgefüllt.
Zu diesem Zeitpunkt habe ich versucht new JsonSerializerSettings(){CheckAdditionalContent = true}
, den Deserialisierungsaufruf zu ergänzen. das hat nichts getan.
Noch ein Hinweis. Die Konstruktorparameter stimmen genau mit den Namen der Felder überein, außer dass die Parameter mit einem Kleinbuchstaben beginnen. Ich würde nicht denken, dass dies eine Rolle spielen würde, da die Deserialisierung, wie bereits erwähnt, ohne Standardkonstruktor einwandfrei funktioniert.
Hier ist ein Beispiel meiner Konstruktoren:
public Result() { }
public Result(int? code, string format, Dictionary<string, string> details = null)
{
Code = code ?? ERROR_CODE;
Format = format;
if (details == null)
Details = new Dictionary<string, string>();
else
Details = details;
}
Antworten:
Json.Net bevorzugt die Verwendung des Standardkonstruktors (ohne Parameter) für ein Objekt, falls vorhanden. Wenn mehrere Konstruktoren vorhanden sind und Json.Net einen nicht standardmäßigen verwenden soll, können Sie das
[JsonConstructor]
Attribut dem Konstruktor hinzufügen, den Json.Net aufrufen soll.Es ist wichtig, dass die Konstruktorparameternamen mit den entsprechenden Eigenschaftsnamen des JSON-Objekts übereinstimmen (Groß- und Kleinschreibung ignorieren), damit dies ordnungsgemäß funktioniert. Sie müssen jedoch nicht unbedingt für jede Eigenschaft des Objekts einen Konstruktorparameter haben. Für JSON-Objekteigenschaften, die nicht von den Konstruktorparametern abgedeckt werden, versucht Json.Net, die öffentlichen Eigenschaftszugriffsfunktionen (oder mit gekennzeichneten Eigenschaften / Feldern
[JsonProperty]
) zu verwenden, um das Objekt nach dem Erstellen zu füllen .Wenn Sie Ihrer Klasse keine Attribute hinzufügen oder den Quellcode für die Klasse, die Sie deserialisieren möchten, nicht anderweitig steuern möchten, können Sie auch einen benutzerdefinierten JsonConverter erstellen, um Ihr Objekt zu instanziieren und zu füllen . Beispielsweise:
Fügen Sie dann den Konverter zu Ihren Serializer-Einstellungen hinzu und verwenden Sie die Einstellungen beim Deserialisieren:
quelle
JsonConverter
für Ihre Klasse erstellen . Dies würde die Abhängigkeit entfernen, aber dann müssten Sie das Instanziieren und Auffüllen des Objekts selbst im Konverter durchführen. Es könnte auch möglich sein, einen benutzerdefiniertenContractResolver
Benutzer zu schreiben , der Json.Net anweist, den anderen Konstruktor durch Ändern seines zu verwendenJsonObjectContract
. Dies könnte sich jedoch als etwas schwieriger erweisen, als es sich anhört.using Newtonsoft.Json;
Ein bisschen spät und hier nicht genau geeignet, aber ich werde meine Lösung hier hinzufügen, weil meine Frage als Duplikat dieser geschlossen wurde und weil diese Lösung völlig anders ist.
Ich brauchte eine allgemeine Methode, um anzuweisen
Json.NET
, den spezifischsten Konstruktor für einen benutzerdefinierten Strukturtyp zu bevorzugen, damit ich dieJsonConstructor
Attribute weglassen kann, die dem Projekt, in dem jede solche Struktur definiert ist, eine Abhängigkeit hinzufügen würden.Ich habe ein wenig rückentwickelt und einen benutzerdefinierten Vertragsauflöser implementiert, bei dem ich die
CreateObjectContract
Methode zum Hinzufügen meiner benutzerdefinierten Erstellungslogik überschrieben habe .Ich benutze es so.
quelle
objectType.IsValueType
) aufgehoben und das funktioniert großartig, danke!Basierend auf einigen der Antworten hier habe ich eine
CustomConstructorResolver
zur Verwendung in einem aktuellen Projekt geschrieben und dachte, es könnte jemand anderem helfen.Es unterstützt die folgenden Auflösungsmechanismen, die alle konfigurierbar sind:
Newtonsoft.Json.JsonConstructorAttribute
.Hier ist die vollständige Version mit XML-Dokumentation als Kern: https://gist.github.com/maverickelementalch/80f77f4b6bdce3b434b0f7a1d06baa95
Feedback erwünscht.
quelle
Das Standardverhalten von Newtonsoft.Json wird die
public
Konstruktoren finden. Wenn Ihr Standardkonstruktor nur zum Enthalten von Klassen oder derselben Assembly verwendet wird, können Sie die Zugriffsebene aufprotected
oderinternal
so reduzieren , dass Newtonsoft.Json den gewünschtenpublic
Konstruktor auswählt .Zugegebenermaßen ist diese Lösung eher auf bestimmte Fälle beschränkt.
quelle
Lösung:
Modell:
quelle