Deserialisieren von Json zu abgeleiteten Typen in Asp.Net Web API
Rufe ich eine Methode, meine WebAPI senden eines json, ich möchte zu entsprechen (oder binden) mit einem Modell.
In der Steuerung habe ich eine Methode wie:
public Result Post([ModelBinder(typeof(CustomModelBinder))]MyClass model);
'MyClass', die als parameter angegeben ist eine abstrakte Klasse. Ich möchte, dass, je nachdem, welche Art von json übergeben, die richtige geerbten Klasse instanziiert wird.
Um es zu erreichen, bin ich versucht zu implementieren eine benutzerdefinierte binder. Das problem ist, dass (ich weiß nicht, ob es ist sehr einfach, aber ich kann nichts finden) ich weiß nicht, wie das abrufen der rohen Json (oder besser, die irgendeine Art von Serialisierung), die in der Anfrage.
Sehe ich:
- actionContext.Anfrage.Inhalt
Aber alle Methoden ausgesetzt sind als asynchrone. Ich weiß nicht, wer dieser passt, wobei die Modell generieren, um die controller-Methode...
Vielen Dank!
InformationsquelleAutor der Frage IoChaos | 2012-09-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brauchen Sie nicht ein benutzerdefiniertes Modell-binder. Und du musst auch nicht muck über mit der Anforderungspipeline.
Werfen Sie einen Blick auf diese andere SO: Gewusst wie: implementieren von benutzerdefinierten JsonConverter in JSON.NET Deserialisieren eine Liste von base class-Objekte?.
Habe ich dieses als basis für meine eigene Lösung für das gleiche problem.
Beginnend mit der
JsonCreationConverter<T>
verwiesen, dass SO (leicht geändert und beheben Sie Probleme mit der Serialisierung von Typen, die in Antworten):Und jetzt können Sie kommentieren Ihre Art mit der
JsonConverterAttribute
, zeigen Json.Net um einen benutzerdefinierten Konverter:Nun können Sie den Basistyp als parameter:
Und wenn wir post:
Dann
arg
wäre eine Instanz derDerivedClass
, aber wenn wir geschrieben:Dann würden Sie erhalten eine Instanz des
DefaultClass
.BEARBEITEN - Warum ich bevorzuge diese Methode, um
TypeNameHandling.Auto/All
Glaube ich, dass mit der
TypeNameHandling.Auto/All
durch den Ausverkauf von JotaBe ist nicht immer die ideale Lösung. Es könnte gut sein, in diesem Fall - aber ich persönlich werde es nicht tun, es sei denn:Wenn Json.Net
TypeNameHandling.Auto
oderAll
verwendet werden, kann Ihre web-server wird das versenden geben Sie die Namen im formatMyNamespace.MyType, MyAssemblyName
.Ich gesagt habe, in die Kommentare, ich denke, das ist ein Sicherheitsrisiko. Erwähnt dies in einigen Unterlagen, die ich Lesen von Microsoft. Es ist nicht erwähnt, nicht mehr, es scheint, aber ich immer noch das Gefühl, es ist ein berechtigtes Anliegen. Ich glaube nicht, immer verfügbar machen möchten namespace qualifizierten Typnamen und assembly-Namen mit der Außenwelt. Es steigt meine Angriffsfläche. Also, ja, ich kann es nicht haben
Object
Eigenschaften/Parameter meiner API-Typen, aber wer ist um zu sagen, der rest meiner Seite wird vollständig Loch-frei sind? Wer ist um zu sagen, eine Zukunft, Endpunkt nicht aussetzen, die Fähigkeit zu nutzen, geben Sie die Namen? Warum nehmen Sie diese chance, nur weil es einfacher ist?Auch - wenn Sie das schreiben eines 'richtigen' API, d.h. speziell für den Verzehr durch Dritte und nicht nur für sich selbst, und Sie sind mit Web-API, dann sind Sie wahrscheinlich auf der Suche zu nutzen die JSON/XML-content-type-handling (als minimum). Sehen Sie, wie weit Sie bekommen versuchen, Dokumentation zu schreiben, die einfach zu konsumieren, das bezieht sich auf alle API-Typen unterschiedlich für XML-und JSON-Formate.
Durch überschreiben wie JSON.Net versteht der Typ-Namen, können Sie bringen die beiden in Einklang, so dass die Wahl zwischen XML/JSON für den Anrufer rein auf den Geschmack, und nicht, weil die Typ-Namen sind leichter zu merken, in die eine oder andere.
InformationsquelleAutor der Antwort Andras Zoltan
Brauchen Sie nicht, um es zu implementieren selbst. JSON.NET hat native Unterstützung für.
Müssen Sie die gewünschte option TypeNameHandling für die JSON-Formatierer, wie diese (in
global.asax
application start event):Wenn Sie angeben
Auto
, wie in dem obigen Beispiel wird der parameter deserialisiert werden, um den angegebenen Typ in die$type
- Eigenschaft des Objekts. Wenn die$type
Eigenschaft fehlt, wird es deserialisiert werden, zum Typ des Parameters. So müssen Sie nur den Typ angeben, wenn man die übergabe eines Parameters von einem abgeleiteten Typ. (Dies ist die flexibelste option).Beispielsweise, wenn Sie diesen parameter übergeben, um eine Web-API-Aktion:
Wird der parameter deserialisiert ein Objekt
MyNamespace.MyType
Klasse.Funktioniert das auch her sub-Eigenschaften, D. H., Sie können ein Objekt wie dieses, die angibt, dass eine innere Eigenschaft ist von einem bestimmten Typ
Hier sehen Sie eine auf Probe JSON.NET Dokumentation von TypeNameHandling.Auto.
Dies funktioniert zumindest seit JSON.NET 4 release.
HINWEIS
Brauchen Sie nicht zu dekorieren Sie alles mit attirbutes, oder jede andere Anpassung. Es wird funktionieren, ohne irgendwelche änderungen in Ihrer Web-API-code.
WICHTIGER HINWEIS
Die $type muss die erste Eigenschaft des JSON-serialisiertes Objekt. Wenn nicht, wird es ignoriert.
VERGLEICH ZU BENUTZERDEFINIERTEN JsonConverter/JsonConverterAttribute
Ich bin Vergleich der nativen Lösung diese Antwort.
Zur Umsetzung der
JsonConverter
/JsonConverterAttribute
:JsonConverter
, und eine benutzerdefinierteJsonConverterAttribute
JsonConverter
wenn Ihre Typen oder Eigenschaften ändernIn der Autor der die Antwort gibt ' s einen Kommentar bezüglich der Sicherheit. Es sei denn, Sie tun etwas falsch (wie die Annahme einer zu generischen Typ für Ihren parameter, wie
Object
) es gibt keine Gefahr, sich eine Instanz von der falschen Art: JSON.NET native Lösung nur instanziiert ein Objekt der Typ des Parameters, oder ein abgeleiteter Typ (wenn nicht, bekommen Sienull
).- Und das sind die Vorteile JSON.NET native Lösung:
TypeNameHandling
einmal in Ihrem app)(1): wenn Sie möchten empfangen der Parameterwerte, die nicht Erben von der gleichen Basis geben, das wird nicht funktionieren, aber ich sehe keinen Sinn dabei
So, ich kann nicht finden, keine Nachteile und viele Vorteile auf JSON.NET Lösung.
WARUM VERWENDEN von BENUTZERDEFINIERTEN JsonConverter/JsonConverterAttribute
Dies ist eine gute, funktionierende Lösung, mit der Anpassung, das kann modifiziert oder erweitert werden, um eine Anpassung an Ihre speziellen Fall.
Wenn Sie wollen, etwas zu tun, dass die native-Lösung nicht, wie customizing der Art den Namen oder die Herleitung von dem Typ der parameter, basierend auf den verfügbaren property-Namen, dann verwenden Sie diese Lösung angepasst an Ihre eigenen Fall. Der andere kann nicht angepasst werden, und nicht Arbeit für Ihre Bedürfnisse.
InformationsquelleAutor der Antwort JotaBe
Aufrufen Sie können async-Methoden in der Regel wird Ihre Ausführung wird einfach unterbrochen, bis die Methode gibt, und Sie zurückkehren können Sie das Modell in standard-Weise. Nur einen Anruf wie diesen:
Wird es Ihnen rohen JSON.
InformationsquelleAutor der Antwort tpeczek
Wenn Sie möchten, verwenden Sie die TypeNameHandling.Auto, aber sich mit Sicherheit oder nicht, wie api-Verbraucher benötigen, die Ebene von hinter den kulissen wissen, das Sie behandeln können, die $Typ Deserialisieren von Ihr selbst.
Dann Haken Sie diese in die weltweiten.asax.Anwendung__Start
schließlich benutzt habe ich eine wrapper-Klasse und [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)] auf eine properpty mit dem Objekt, mit verschiedenen Typen wie ich nicht in der Lage gewesen, um es zu arbeiten, indem Sie die Konfiguration in der aktuellen Klasse.
Dieser Ansatz ermöglicht es dem Verbraucher, um die benötigte Informationen in Ihrer Anfrage, wobei die Dokumentation der zulässigen Werte zu sein, unabhängig von der Plattform, einfach zu wechseln und leicht zu verstehen. Alle die zimmerreserviereung, ohne das eigene zu schreiben, converster.
Kredit : https://mallibone.com/post/serialize-object-inheritance-with-json.net
für die mit mir die custom deserializer der Feld-Eigenschaft.
InformationsquelleAutor der Antwort user8606451