Wie zähle ich über ein JObject auf?

109

Ich versuche zu bestimmen, wie auf die Daten in meinem JObject zugegriffen werden soll, und ich kann für mein ganzes Leben nicht bestimmen, wie ich sie verwenden soll.

JObject Object = (JObject)Response.Data["my_key"];

Ich kann es mit Console.WriteLine (Object) auf der Konsole drucken und sehe die Daten wie folgt:

{
 "my_data" : "more of my string data"
...
}

Aber ich habe KEINE Ahnung, wie ich es einfach durchlaufen / aufzählen soll. Hat jemand irgendwelche Ideen? Ich bin gerade so ratlos.

Geesu
quelle

Antworten:

166

Wenn Sie sich die DokumentationJObject ansehen , werden Sie sehen, dass sie implementiert wird IEnumerable<KeyValuePair<string, JToken>>. Sie können es also einfach mit folgenden Schritten durchlaufen foreach:

foreach (var x in obj)
{
    string name = x.Key;
    JToken value = x.Value;
    
}
svick
quelle
3
Dies ist korrekt, aber aus Gründen, die ich nicht verstehe, können Sie es nicht mit Linq verwenden, es sei denn, Sie wandeln es explizit in den Aufzählungstyp um. Dh du ((IEnumerable<KeyValuePair<string, JToken>>)obj).Select(...)statt schlicht alt obj.Select(...); oder zumindest fand ich es einen Teil meines Codes.
Adrian Ratnapala
2
@AdrianRatnapala Ist Ihr Objekt als dynamisch deklariert? Erweiterungsmethoden (wie Enumerable.Select) funktionieren damit nicht.
Svick
1
Nein, in meinem Fall objhatte Typ JObject; aber JObjectscheint ähnliche Probleme zu haben dynamic. Der Compiler kann die Typargumente nicht ableiten .Select. Ich kann sie explizit geben, funktioniert obj.Select<KeyValuePair<string, JToken>, (result type)>(...)auch für mich
Adrian Ratnapala
3
@AdrianRatnapala Hmm, du hast recht. Es ist, weil JObjectbeide IEnumerable<KeyValuePair<string, JToken>>und IEnumerable<JToken>(indirekt durch JContainer) implementiert .
Svick
3
Wie verwende ich es nun für verschachteltes JSON? Wenn der "Wert" beispielsweise einen anderen Satz von Schlüssel: Wert-Paaren enthält, wie kann ich den verwenden JToken value, um den nächsten Satz von Paaren zu durchlaufen?
AlbatrossCafe
53

JObjects können über JProperty- Objekte aufgelistet werden, indem sie in ein JToken umgewandelt werden :

foreach (JProperty x in (JToken)obj) { // if 'obj' is a JObject
    string name = x.Name;
    JToken value = x.Value;
}

Wenn Sie ein verschachteltes JObject in einem anderen JObject haben, müssen Sie es nicht umwandeln, da der Accessor ein JToken zurückgibt:

foreach (JProperty x in obj["otherObject"]) { // Where 'obj' and 'obj["otherObject"]' are both JObjects
    string name = x.Name;
    JToken value = x.Value;
}
Daniel
quelle
3
Sie können linq auch bequem wie folgt verwenden : obj.Properties().Select(p => p.Name + ": " + p.Value).
itslittlejohn
Dies war genau die Information, die ich suchte. Ich danke dir sehr!
Jhoepken
15

Die Antwort hat bei mir nicht funktioniert. Ich weiß nicht, wie es so viele Stimmen bekommen hat. Obwohl es mir geholfen hat, mich in eine Richtung zu weisen.

Dies ist die Antwort, die für mich funktioniert hat:

foreach (var x in jobj)
{
    var key = ((JProperty) (x)).Name;
    var jvalue = ((JProperty)(x)).Value ;
}
jaxxbo
quelle
1
Damit (nach dieser Zeile: JObject priceComplianceJson = JObject.Parse (File.ReadAllText (fullPath));) erhalte ich: "Typ 'System.Collections.Generic.KeyValuePair <string, Newtonsoft.Json.Linq.JToken>' kann nicht konvertiert werden." zu 'Newtonsoft.Json.Linq.JProperty' "Das Entfernen des Castings funktioniert jedoch: var key = x.Key; var jvalue = x.Value; - Zumindest kompiliert es ... Ich werde die Funktionalität morgen tschechisch.
B. Clay Shannon
3

Für Leute wie mich, Linq-Süchtige und basierend auf der Antwort von svick , hier ein Linq-Ansatz:

using System.Linq;
//...
//make it linq iterable. 
var obj_linq = Response.Cast<KeyValuePair<string, JToken>>();

Jetzt können Sie Linq-Ausdrücke wie folgt erstellen:

JToken x = obj_linq
          .Where( d => d.Key == "my_key")
          .Select(v => v)
          .FirstOrDefault()
          .Value;
string y = ((JValue)x).Value;

Oder nur:

var y = obj_linq
       .Where(d => d.Key == "my_key")
       .Select(v => ((JValue)v.Value).Value)
       .FirstOrDefault();

Oder dieses, um alle Daten zu durchlaufen:

obj_linq.ToList().ForEach( x => { do stuff } ); 
dani herrera
quelle