Jak wyliczać za pomocą JObject?


111

Próbuję ustalić, jak uzyskać dostęp do danych znajdujących się w moim JObject i do końca życia nie mogę określić, jak z nich korzystać.

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

Mogę go wydrukować na konsoli robiąc Console.WriteLine (Object) i widzę dane, wygląda to tak:

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

Ale nie mam pojęcia, jak po prostu iterować / wyliczać przez to, ktoś ma jakieś pomysły? Jestem teraz bardzo zagubiony.

Odpowiedzi:


167

Jeśli spojrzysz na dokumentację programuJObject , zobaczysz, że implementuje IEnumerable<KeyValuePair<string, JToken>>. Możesz więc iterować po prostu używając foreach:

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

3
To jest poprawne, ale z powodów, których nie rozumiem, nie możesz go używać z Linq, chyba że jawnie rzutujesz na wyliczalny typ. To znaczy ty ((IEnumerable<KeyValuePair<string, JToken>>)obj).Select(...)zamiast zwykłego starego obj.Select(...); a przynajmniej to właśnie znalazłem jako część mojego kodu.
— Adrian Ratnapala

2
@AdrianRatnapala Czy twój obiekt jest zadeklarowany jako dynamiczny? Metody rozszerzające (takie jak Enumerable.Select) nie działają z tym.
— svick

1
Nie, w moim przypadku objmiał typ JObject; ale JObjectwydaje się mieć podobne problemy do dynamic. Kompilator nie może wywnioskować argumentów typu .Select. Mogę je podać wprost, obj.Select<KeyValuePair<string, JToken>, (result type)>(...)działa też dla mnie
— Adrian Ratnapala

3
@AdrianRatnapala Hmm, masz rację. Dzieje się tak, ponieważ JObjectwdraża oba IEnumerable<KeyValuePair<string, JToken>>i IEnumerable<JToken>(pośrednio przez JContainer).
— svick

3
Jak mam go teraz używać do zagnieżdżonych JSON? Na przykład, jeśli „wartość” zawiera inny zestaw par klucz: wartość, w jaki sposób mogę użyć JToken valuedo iteracji w kolejnym zestawie par?
— AlbatrossCafe

53

JObjects można wyliczyć za pomocą obiektów JProperty , rzutując je na JToken :

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

Jeśli masz zagnieżdżony JObject w innym JObject, nie musisz rzutować, ponieważ akcesor zwróci JToken:

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

3
Można również wygodnie używać LINQ tak: obj.Properties().Select(p => p.Name + ": " + p.Value).
— itslittlejohn

To była dokładnie ta informacja, której szukałem. Dziękuję bardzo!
— jhoepken

15

Odpowiedź nie zadziałała dla mnie. Nie wiem, skąd wzięło się tyle głosów. Chociaż pomogło mi to wskazać kierunek.

Oto odpowiedź, która zadziałała dla mnie:

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

1
Z tym (po tym wierszu: JObject priceComplianceJson = JObject.Parse (File.ReadAllText (fullPath));) otrzymuję komunikat „Nie można przekonwertować typu„ System.Collections.Generic.KeyValuePair <string, Newtonsoft.Json.Linq.JToken> ” to 'Newtonsoft.Json.Linq.JProperty' "Usunięcie rzutowania działa jednak: var key = x.Key; var jvalue = x.Value; - przynajmniej się kompiluje ... Jutro poprawię funkcjonalność.
— B. Clay Shannon

3

Dla ludzi takich jak ja, uzależnionych od linq i w oparciu o odpowiedź Svicka , tutaj podejście linq:

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

Teraz możesz tworzyć wyrażenia linq takie jak:

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

Lub tylko:

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

Lub ten do iteracji po wszystkich danych:

obj_linq.ToList().ForEach( x => { do stuff } ); 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.