Comment énumérer via un JObject?

111

J'essaie de déterminer comment accéder aux données qui se trouvent dans mon JObject et je ne peux pas pour la vie de moi déterminer comment l'utiliser.

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

Je peux l'imprimer sur la console en faisant Console.WriteLine (Object) et je vois les données, cela ressemble à:

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

Mais je n'ai aucune idée de comment simplement itérer / énumérer à travers elle, quelqu'un a des idées? Je suis tellement perdu en ce moment.

Geesu
la source

Réponses:

167

Si vous regardez la documentation deJObject , vous verrez qu'elle implémente IEnumerable<KeyValuePair<string, JToken>>. Ainsi, vous pouvez le parcourir simplement en utilisant un foreach:

foreach (var x in obj)
{
    string name = x.Key;
    JToken value = x.Value;
    
}
svick
la source
3
C'est correct, mais pour des raisons que je ne comprends pas, vous ne pouvez pas l'utiliser avec Linq à moins que vous ne convertissiez explicitement le type énumérable. Ie vous ((IEnumerable<KeyValuePair<string, JToken>>)obj).Select(...)au lieu de plaine-vieux obj.Select(...); ou du moins c'est ce que j'ai trouvé dans une partie de mon code.
Adrian Ratnapala
2
@AdrianRatnapala Votre obj est-il déclaré dynamique? Les méthodes d'extension (comme Enumerable.Select) ne fonctionnent pas avec cela.
svick
1
Non, dans mon cas, objj'avais le type JObject; mais JObjectsemble avoir des problèmes similaires à dynamic. Le compilateur ne peut pas déduire les arguments de type .Select. Je peux les donner explicitement, cela obj.Select<KeyValuePair<string, JToken>, (result type)>(...)fonctionne aussi pour moi
Adrian Ratnapala
3
@AdrianRatnapala Hmm, vous avez raison. C'est parce que JObjectimplémente à la fois IEnumerable<KeyValuePair<string, JToken>>et IEnumerable<JToken>(indirectement à travers JContainer).
svick
3
Maintenant, comment puis-je l'utiliser pour JSON imbriqué? Par exemple, si la "valeur" contient un autre ensemble de paires clé: valeur, comment puis-je utiliser le JToken valuepour parcourir l'ensemble de paires suivant?
AlbatrossCafe
53

Les JObjects peuvent être énumérés via des objets JProperty en le convertissant en JToken :

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

Si vous avez un JObject imbriqué à l'intérieur d'un autre JObject, vous n'avez pas besoin d'effectuer un cast car l'accesseur renverra un JToken:

foreach (JProperty x in obj["otherObject"]) { // Where 'obj' and 'obj["otherObject"]' are both JObjects
    string name = x.Name;
    JToken value = x.Value;
}
Daniel
la source
3
Vous pouvez également utiliser commodément LINQ comme ceci: obj.Properties().Select(p => p.Name + ": " + p.Value).
itslittlejohn
C'était exactement l'information que je recherchais. Merci beaucoup!
jhoepken
15

La réponse n'a pas fonctionné pour moi. Je ne sais pas comment il a obtenu autant de votes. Bien que cela ait aidé à me diriger dans une direction.

Voici la réponse qui a fonctionné pour moi:

foreach (var x in jobj)
{
    var key = ((JProperty) (x)).Name;
    var jvalue = ((JProperty)(x)).Value ;
}
jaxxbo
la source
1
Avec cela (après cette ligne: JObject priceComplianceJson = JObject.Parse (File.ReadAllText (fullPath));) J'obtiens, "Impossible de convertir le type 'System.Collections.Generic.KeyValuePair <string, Newtonsoft.Json.Linq.JToken>' to 'Newtonsoft.Json.Linq.JProperty' "La suppression du casting fonctionne, cependant: var key = x.Key; var jvalue = x.Value; - au moins il compile ... Je vais tchèque la fonctionnalité demain.
B. Clay Shannon
3

Pour les gens comme moi, les accros de linq , et basé sur la réponse de svick , voici une approche linq:

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

Vous pouvez maintenant créer des expressions linq comme:

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

Ou juste:

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

Ou celui-ci pour itérer sur toutes les données:

obj_linq.ToList().ForEach( x => { do stuff } ); 
Dani Herrera
la source