Ich mag das ExpandoObject
beim Kompilieren eines serverseitigen dynamischen Objekts zur Laufzeit sehr, aber ich habe Probleme, dieses Ding während der JSON-Serialisierung zu reduzieren. Zuerst instanziiere ich das Objekt:
dynamic expando = new ExpandoObject();
var d = expando as IDictionary<string, object>;
expando.Add("SomeProp", SomeValueOrClass);
So weit, ist es gut. In meinem MVC-Controller möchte ich dies dann als JsonResult senden, also mache ich Folgendes:
return new JsonResult(expando);
Dadurch wird der JSON wie folgt serialisiert, damit er vom Browser verwendet werden kann:
[{"Key":"SomeProp", "Value": SomeValueOrClass}]
ABER was ich wirklich gerne sehen würde ist:
{SomeProp: SomeValueOrClass}
Ich weiß, dass ich dies erreichen kann, wenn ich dynamic
anstelle von ExpandoObject
- JsonResult
die dynamic
Eigenschaften und Werte in ein einzelnes Objekt serialisieren kann (ohne Schlüssel- oder Wertgeschäft), aber der Grund, den ich verwenden muss, ExpandoObject
ist, dass ich nicht alle kenne Die Eigenschaften, die ich bis zur Laufzeit für das Objekt haben möchte , und soweit ich weiß, kann ich eine Eigenschaft nicht dynamisch zu einer hinzufügen, dynamic
ohne eine zu verwenden ExpandoObject
.
Ich muss möglicherweise das Geschäft "Schlüssel", "Wert" in meinem Javascript durchsehen, aber ich hatte gehofft, dies herauszufinden, bevor ich es an den Kunden sende. Danke für Ihre Hilfe!
quelle
Antworten:
Sie können auch einen speziellen JSONConverter erstellen, der nur für ExpandoObject funktioniert, und ihn dann in einer Instanz von JavaScriptSerializer registrieren. Auf diese Weise können Sie Arrays von expando, Kombinationen von expando-Objekten und ... serialisieren, bis Sie eine andere Art von Objekt finden, die nicht korrekt serialisiert wird ("wie Sie wollen"), dann einen anderen Konverter erstellen oder einen anderen Typ hinzufügen dieses. Hoffe das hilft.
Konverter verwenden
quelle
NotImplementedException
um so etwas hinzuzufügenserializer.Deserialize<ExpandoObject>(json);
, bietet @theburningmonk eine Lösung , die für mich funktioniert hat.Mit JSON.NET können Sie SerializeObject aufrufen, um das expando-Objekt zu "reduzieren":
Wird ausgegeben:
Im Kontext eines ASP.NET MVC-Controllers kann das Ergebnis mit der Content-Methode zurückgegeben werden:
quelle
Folgendes habe ich getan, um das von Ihnen beschriebene Verhalten zu erreichen:
Die Kosten sind, dass Sie eine Kopie der Daten erstellen, bevor Sie sie serialisieren.
quelle
ExpandoObject
bietet Ihnen viel mehr Flexibilität als ein einfaches Wörterbuch. Obwohl das obige Beispiel dies nicht demonstriert, können Sie die dynamischen Funktionen von verwendenExpandoObject
, um die Eigenschaften hinzuzufügen, die Sie in Ihrem JSON haben möchten. Ein normalesDictioanry
Objekt wird problemlos in JSON konvertiert. Durch die Konvertierung können Sie dieExpandoObject
benutzerfreundliche Dynamik auf einfache Weise in ein Format umwandeln, das JSON-fähig ist. Sie haben jedoch Recht, das obige Beispiel wäre eine Rediculus-Verwendung vonExpandoObject
; ein einfachesDictionary
wäre viel besser.Ich habe dieses Problem gelöst, indem ich eine Erweiterungsmethode geschrieben habe, die das ExpandoObject in eine JSON-Zeichenfolge konvertiert:
Dies nutzt die ausgezeichnete Newtonsoft- Bibliothek.
JsonResult sieht dann so aus:
Und dies wird an den Browser zurückgegeben:
Und ich kann es in Javascript verwenden, indem ich dies tue ( hier referenziert ):
Ich hoffe das hilft!
quelle
Ich konnte das gleiche Problem mit JsonFx lösen .
Ausgabe:
quelle
Ich ging noch einen Schritt weiter und suchte nach Listenobjekten, wodurch der Schlüsselwert-Unsinn beseitigt wurde. :) :)
quelle
Dies mag für Sie nicht nützlich sein, aber ich hatte eine ähnliche Anforderung, verwendete jedoch ein SerializableDynamicObject
Ich habe den Namen des Wörterbuchs in "Felder" geändert und dies wird dann mit Json.Net serialisiert, um json zu erzeugen, das wie folgt aussieht:
{"Felder": {"Eigenschaft1": "Wert1", "Eigenschaft2": "Wert2" usw. wobei Eigenschaft1 und Eigenschaft2 dynamisch hinzugefügte Eigenschaften sind - dh Wörterbuchschlüssel
Es wäre perfekt, wenn ich die zusätzliche Eigenschaft "Felder" entfernen könnte, die den Rest einschließt, aber ich habe diese Einschränkung umgangen.
Die Antwort wurde auf Anfrage von dieser Frage verschoben
quelle
Dies ist eine späte Antwort, aber ich hatte das gleiche Problem, und diese Frage half mir, sie zu lösen. Zusammenfassend dachte ich, ich sollte meine Ergebnisse veröffentlichen, in der Hoffnung, dass dies die Implementierung für andere beschleunigt.
Zuerst das ExpandoJsonResult, von dem Sie eine Instanz in Ihrer Aktion zurückgeben können. Oder Sie können die Json-Methode in Ihrem Controller überschreiben und dort zurückgeben.
Dann den Konverter (der sowohl Serialisierung als auch De-Serialisierung unterstützt. Ein Beispiel für die De-Serialisierung finden Sie weiter unten).
In der ExpandoJsonResult-Klasse können Sie sehen, wie Sie sie für die Serialisierung verwenden. Erstellen Sie zum De-Serialisieren den Serializer und registrieren Sie den Konverter auf die gleiche Weise, verwenden Sie ihn jedoch
Ein großes Dankeschön an alle Teilnehmer hier, die mir geholfen haben.
quelle
Bei Verwendung der Rückgabe von dynamischem ExpandoObject von WebApi in ASP.Net 4 scheint der Standard-JSON-Formatierer ExpandoObjects in ein einfaches JSON-Objekt zu reduzieren.
quelle
JsonResult
verwendet,JavaScriptSerializer
die tatsächlich (den Beton) deserialisieren,Dictionary<string, object>
wie Sie wollen.Es gibt eine Überlastung des
Dictionary<string, object>
Konstruktors, die benötigt wirdIDictionary<string, object>
.ExpandoObject
GeräteIDictionary<string, object>
(ich denke, Sie können sehen, wohin ich hier gehe ...)Einstufiges ExpandoObject
Eine Codezeile mit allen integrierten Typen :)
Verschachtelte ExpandoObjects
Wenn Sie
ExpandoObject
s verschachteln, müssen Sie sie natürlich alle rekursiv inDictionary<string, object>
s konvertieren :Ihr endgültiger Code wird
quelle
Es scheint, als würde der Serializer das Expando in ein Wörterbuch umwandeln und es dann serialisieren (also das Schlüssel- / Wertgeschäft). Haben Sie versucht, Deserializing als Wörterbuch zu verwenden und dieses dann auf ein Expando zurückzuführen?
quelle
Ich hatte nur das gleiche Problem und fand etwas ziemlich Seltsames heraus. Wenn ich mache:
Es funktioniert, aber nur, wenn meine Methode das HttpPost-Attribut verwendet. Wenn ich HttpGet benutze, erhalte ich eine Fehlermeldung. Meine Antwort funktioniert also nur auf HttpPost. In meinem Fall war es ein Ajax-Aufruf, damit ich HttpGet durch HttpPost ändern konnte.
quelle