Deserialisieren Sie das json-Objekt mithilfe von Json.net in ein dynamisches Objekt

426

Ist es möglich, ein dynamisches Objekt aus einer JSON-Deserialisierung mit json.net zurückzugeben? Ich möchte so etwas machen:

dynamic jsonResponse = JsonConvert.Deserialize(json);
Console.WriteLine(jsonResponse.message);
Ryudice
quelle
1
Erwägen Sie, eine C # -Klasse aus JSON json2csharp.com zu generieren und eine generierte Klasse anstelle einer dynamischen zu verwenden
Michael Freidgeim
Mögliches Duplikat von Deserialize JSON in C # Dynamic Object?
MeJustAndrew
Wie schlagen Sie stackOverflow vor, eine Frage als "zu alt" zu schließen? Es ist sechs Jahre her, seitdem gibt es für jede Version von .net gültige Antworten und vernünftige Vorschläge ... so viele, dass sie nicht mehr wirklich hilfreich sind.
Andrew Lorien

Antworten:

546

Mit Json.NET können wir dies tun:

dynamic d = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}");

Console.WriteLine(d.number);
Console.WriteLine(d.str);
Console.WriteLine(d.array.Count);

Ausgabe:

 1000
 string
 6

Dokumentation hier: LINQ to JSON mit Json.NET

Siehe auch JObject.Parse und JArray.Parse

Michael Pakhantsov
quelle
36
Beachten Sie, dass für Arrays die Syntax lautet JArray.Parse.
jgillich
4
Warum müssen wir ein dynamisches Wort verwenden? Ich habe Angst, noch nie benutzt: D
MonsterMMORPG
3
In VB.Net müssen Sie tunDim d As Object = JObject.Parse("{number:1000, str:'string', array: [1,2,3,4,5,6]}")
ilans
2
@MonsterMMORPG Das solltest du sein :) Dynamisch ist unter fast allen Umständen ein Anti-Pattern, aber hin und wieder kann es vorkommen, dass es sinnvoll ist, es zu verwenden.
Pluc
4
Bei Newtonsoft.Json 8.0.3 (.NET 4.5.2): Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ist aufgetreten. HResult = -2146233088 Message = 'Newtonsoft.Json.Linq.JObject' enthält keine Definition für 'number' Source = Microsoft .CSharp StackTrace: bei Microsoft.CSharp.RuntimeBinder.RuntimeBinderController.SubmitError (CError pError)
user4698855
107

Ab Json.NET 4.0 Release 1 gibt es native dynamische Unterstützung:

[Test]
public void DynamicDeserialization()
{
    dynamic jsonResponse = JsonConvert.DeserializeObject("{\"message\":\"Hi\"}");
    jsonResponse.Works = true;
    Console.WriteLine(jsonResponse.message); // Hi
    Console.WriteLine(jsonResponse.Works); // True
    Console.WriteLine(JsonConvert.SerializeObject(jsonResponse)); // {"message":"Hi","Works":true}
    Assert.That(jsonResponse, Is.InstanceOf<dynamic>());
    Assert.That(jsonResponse, Is.TypeOf<JObject>());
}

Der beste Weg, um die aktuelle Version zu erhalten, ist natürlich NuGet.

Aktualisiert (12.11.2014), um Kommentare zu adressieren:

Das funktioniert einwandfrei. Wenn Sie den Typ im Debugger überprüfen, werden Sie feststellen, dass der Wert tatsächlich dynamisch ist . Der zugrunde liegende Typ ist a JObject. Wenn Sie den Typ steuern möchten (z. B. angeben) ExpandoObject, tun Sie dies.

Geben Sie hier die Bildbeschreibung ein

David Peden
quelle
20
Das scheint nie zu funktionieren. Es wird nur ein JObject zurückgegeben, keine dynamische Variable.
Paul
12
Übrigens funktioniert dies: JsonConvert.DeserializeObject <ExpandoObject> (STRING); mit der richtigen Deserialisierung, so dass wir kein JObject usw. haben
Gutek
2
@Gutek nicht sicher, was Ihr Problem ist. Hast du den Code ausgeführt? Ich habe dem Test Asserts hinzugefügt und eine Eigenschaft hinzugefügt, die nicht im ursprünglichen JSON enthalten ist. Screenshot des Debuggers enthalten.
David Peden
1
@DavidPeden Wenn Sie JObject haben und versuchen, das in Razor zu binden, erhalten Sie Ausnahmen. Die Frage betraf die Deserialisierung in ein dynamisches Objekt - JObject ist dynamisch, enthält jedoch "eigene" Typen wie JValue, keine primitiven Typen. Ich kann den @Model.PropNamen in Razor nicht verwenden, wenn der Rückgabetyp JValue ist.
Gutek
2
Dies funktioniert, aber jede dynamische Eigenschaft ist a JValue. Was mich verwirrte, weil ich im Debugger / Sofortfenster arbeitete und nicht nur strings sah. David zeigt dies im unteren Screenshot. Das JValueist Cabrio, so dass Sie einfach tun könnenstring m = jsonResponse.message
Luke Puplett
66

Wenn Sie nur auf dynamisch deserialisieren, erhalten Sie ein JObject zurück. Mit einem ExpandoObject können Sie das bekommen, was Sie wollen.

var converter = new ExpandoObjectConverter();    
dynamic message = JsonConvert.DeserializeObject<ExpandoObject>(jsonString, converter);
Joshua Peterson
quelle
1
Das Ergebnis kann auch in ein Wörterbuch konvertiert werden
FindOutIslamNow
1
Genau das, wonach ich gesucht habe! Vielen Dank!
DarkDeny
42

Ich weiß, dass dies ein alter Beitrag ist, aber JsonConvert hat tatsächlich eine andere Methode, so wie es wäre

var product = new { Name = "", Price = 0 };
var jsonResponse = JsonConvert.DeserializeAnonymousType(json, product);
Epitka
quelle
23
Das würde bedeuten, eine json-Nutzlast in einen anonymen Typ zu deserialisieren, nicht in einen dynamischen Typ. Anonyme Typen und dynamische Typen sind verschiedene Dinge, und ich glaube nicht, dass dies die gestellte Frage anspricht.
jrista
1
Müssen zwei Variablen verwendet werden? Warum nicht den ersten in der zweiten Anweisung wiederverwenden?
RenniePet
21

Ja, Sie können dies mit JsonConvert.DeserializeObject tun. Um das zu tun, machen Sie einfach:

dynamic jsonResponse = JsonConvert.DeserializeObject(json);
Console.WriteLine(jsonResponse["message"]);
oteal
quelle
1
JsonConvertenthält keine Methode namens Deserialize.
Kann Poyrazoğlu
es sollte nur DeserializeObject sein, aber dies sollte die akzeptierte Antwort sein IMO
superjugy
21

Hinweis: Als ich diese Frage im Jahr 2010 beantwortete, gab es keine Möglichkeit zum Deserialisieren ohne einen Typ. Dadurch konnten Sie deserialisieren, ohne die eigentliche Klasse definieren zu müssen, und eine anonyme Klasse konnte für die Deserialisierung verwendet werden.


Sie benötigen einen Typ, zu dem Sie deserialisieren können. Sie könnten etwas in der Art von:

var product = new { Name = "", Price = 0 };
dynamic jsonResponse = JsonConvert.Deserialize(json, product.GetType());

Meine Antwort basiert auf einer Lösung für .NET 4.0 in JSON Serializer. Der Link zum Deserialisieren zu anonymen Typen ist hier:

http://blogs.msdn.com/b/alexghi/archive/2008/12/22/using-anonymous-types-to-deserialize-json-data.aspx

Phill
quelle
Ich bin bei dir. Ich weiß nicht, warum die Leute das ablehnen. Wenn jemand kann, bitte. Bitte erklären Sie, warum.
PEO
18
Sie stimmen ab, weil es um das Deserialisieren ohne Typ geht.
Richard
4
Die Antwort war zum Zeitpunkt des Schreibens im Jahr 2010 gültig, als es keine andere Lösung gab. Es war sogar die akzeptierte Antwort für einen kurzen Zeitraum, bis die Unterstützung in JSON.NET kam.
Phill
1
Dies erzeugt kein dynamisches Objekt. Dies erzeugt ein JObject, auf das Sie als dynamisch verweisen. Aber es ist immer noch ein JObject im Inneren.
Ghostbust555
5

Wenn Sie JSON.NET mit einer alten Version verwenden, die nicht JObject war.

Dies ist eine weitere einfache Möglichkeit, ein dynamisches Objekt aus JSON zu erstellen: https://github.com/chsword/jdynamic

NuGet installieren

PM> Install-Package JDynamic

Unterstützung für die Verwendung des Zeichenfolgenindex für den Zugriff auf Mitglieder wie:

dynamic json = new JDynamic("{a:{a:1}}");
Assert.AreEqual(1, json["a"]["a"]);

Testfall

Und Sie können dieses Dienstprogramm wie folgt verwenden:

Holen Sie sich den Wert direkt

dynamic json = new JDynamic("1");

//json.Value

2. Holen Sie sich das Mitglied im JSON-Objekt

dynamic json = new JDynamic("{a:'abc'}");
//json.a is a string "abc"

dynamic json = new JDynamic("{a:3.1416}");
//json.a is 3.1416m

dynamic json = new JDynamic("{a:1}");
//json.a is integer: 1

3. Unzählige

dynamic json = new JDynamic("[1,2,3]");
/json.Length/json.Count is 3
//And you can use json[0]/ json[2] to get the elements

dynamic json = new JDynamic("{a:[1,2,3]}");
//json.a.Length /json.a.Count is 3.
//And you can use  json.a[0]/ json.a[2] to get the elements

dynamic json = new JDynamic("[{b:1},{c:1}]");
//json.Length/json.Count is 2.
//And you can use the  json[0].b/json[1].c to get the num.

Andere

dynamic json = new JDynamic("{a:{a:1} }");

//json.a.a is 1.
chsword
quelle
2

Ja, es ist möglich. Ich habe das die ganze Zeit gemacht.

dynamic Obj = JsonConvert.DeserializeObject(<your json string>);

Für nicht native Typen ist es etwas schwieriger. Angenommen, in Ihrem Objekt befinden sich ein ClassA- und ein ClassB-Objekt. Sie werden alle in JObject konvertiert. Was Sie tun müssen, ist:

ClassA ObjA = Obj.ObjA.ToObject<ClassA>();
ClassB ObjB = Obj.ObjB.ToObject<ClassB>();
sk
quelle