Come faccio a enumerare tramite un JObject?


111

Sto cercando di determinare come accedere ai dati che si trovano nel mio JObject e non posso per la vita di determinare come usarli.

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

Posso stamparlo sulla console facendo Console.WriteLine (Object) e vedo i dati, sembra:

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

Ma non ho idea di come iterare / enumerare solo attraverso di esso, qualcuno ha qualche idea? Sono così in perdita adesso.

Risposte:


167

Se guardi la documentazione perJObject , vedrai che implementa IEnumerable<KeyValuePair<string, JToken>>. Quindi, puoi iterare su di esso semplicemente usando un foreach:

foreach (var x in obj)
{
    string name = x.Key;
    JToken value = x.Value;
    …
}

3
Questo è corretto, ma per motivi che non capisco, non puoi usarlo con Linq a meno che non esegui il cast esplicito al tipo enumerabile. Cioè tu ((IEnumerable<KeyValuePair<string, JToken>>)obj).Select(...)invece che semplice vecchio obj.Select(...); o almeno questo è quello che ho trovato una parte del mio codice.
— Adrian Ratnapala

2
@AdrianRatnapala Il tuo oggetto è dichiarato dinamico? I metodi di estensione (come Enumerable.Select) non funzionano con quello.
— svick

1
No, nel mio caso objaveva il tipo JObject; ma JObjectsembra avere problemi simili a dynamic. Il compilatore non può dedurre gli argomenti di tipo a .Select. Posso darli esplicitamente, obj.Select<KeyValuePair<string, JToken>, (result type)>(...)funziona anche per me
— Adrian Ratnapala

3
@AdrianRatnapala Hmm, hai ragione. È perché JObjectimplementa sia IEnumerable<KeyValuePair<string, JToken>>e IEnumerable<JToken>(indirettamente tramite JContainer).
— svick

3
Ora come lo uso per JSON nidificato? Ad esempio, se il "valore" contiene un altro insieme di coppie chiave: valore, come posso utilizzare il JToken valueper scorrere il prossimo insieme di coppie?
— AlbatrossCafe

53

Gli oggetti JO possono essere enumerati tramite oggetti JProperty eseguendo il cast a un JToken :

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

Se hai un JObject annidato all'interno di un altro JObject, non è necessario eseguire il cast perché la funzione di accesso restituirà un JToken:

foreach (JProperty x in obj["otherObject"]) { // Where 'obj' and 'obj["otherObject"]' are both JObjects
    string name = x.Name;
    JToken value = x.Value;
}

3
È possibile anche comodamente usare LINQ in questo modo: obj.Properties().Select(p => p.Name + ": " + p.Value).
— itslittlejohn

Questa era esattamente l'informazione che stavo cercando. Grazie mille!
— jhoepken

15

La risposta non ha funzionato per me. Non so come abbia ottenuto così tanti voti. Anche se mi ha aiutato a indicarmi una direzione.

Questa è la risposta che ha funzionato per me:

foreach (var x in jobj)
{
    var key = ((JProperty) (x)).Name;
    var jvalue = ((JProperty)(x)).Value ;
}

1
Con questo (dopo questa riga: JObject priceComplianceJson = JObject.Parse (File.ReadAllText (fullPath));) ottengo, "Impossibile convertire il tipo 'System.Collections.Generic.KeyValuePair <string, Newtonsoft.Json.Linq.JToken>' a 'Newtonsoft.Json.Linq.JProperty' "La rimozione del casting funziona, però: var key = x.Key; var jvalue = x.Value; - almeno si compila ... domani ceco la funzionalità.
— B. Clay Shannon

3

Per persone come me, dipendenti da linq e in base alla risposta di svick , ecco un approccio linq:

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

Ora puoi creare espressioni linq come:

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

O semplicemente:

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

O questo per iterare su tutti i dati:

obj_linq.ToList().ForEach( x => { do stuff } ); 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.