Как выполнить перечисление с помощью JObject?

111

Я пытаюсь определить, как получить доступ к данным, находящимся в моем JObject, и я не могу, хоть убей, определить, как их использовать.

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

Я могу распечатать его на консоли, выполняя Console.WriteLine (Object), и я вижу данные, это выглядит так:

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

Но я не знаю, как просто перебирать / перечислять его, у кого-нибудь есть идеи? Я сейчас в таком недоумении.

Geesu
источник

Ответы:

167

Если вы посмотрите документацию поJObject , то увидите, что она реализует IEnumerable<KeyValuePair<string, JToken>>. Итак, вы можете перебирать его, просто используя foreach:

foreach (var x in obj)
{
    string name = x.Key;
    JToken value = x.Value;
    
}
svick
источник
3
Это правильно, но по причинам, которые я не понимаю, вы не можете использовать его с Linq, если вы явно не приведете его к перечислимому типу. Т.е. вы ((IEnumerable<KeyValuePair<string, JToken>>)obj).Select(...)вместо старенького obj.Select(...); или, по крайней мере, то, что я нашел, это одна часть моего кода.
Адриан Ратнапала
2
@AdrianRatnapala Ваш объект объявлен динамическим? Методы расширения (например, Enumerable.Select) с этим не работают.
svick
1
Нет, в моем случае objбыл тип JObject; но JObjectпохоже есть проблемы, похожие на dynamic. Компилятор не может определить аргументы типа .Select. Я могу дать их явно, obj.Select<KeyValuePair<string, JToken>, (result type)>(...)мне тоже подходит,
Адриан Ратнапала,
3
@AdrianRatnapala Хм, ты прав. Это потому, что JObjectреализует оба IEnumerable<KeyValuePair<string, JToken>>и IEnumerable<JToken>(косвенно через JContainer).
svick
3
Как теперь использовать его для вложенного JSON? Например, если «значение» содержит другой набор пар ключ: значение, как я могу использовать JToken valueдля перебора следующего набора пар?
AlbatrossCafe
53

Объекты JObject можно перечислить с помощью объектов JProperty, преобразовав их в JToken :

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

Если у вас есть вложенный JObject внутри другого JObject, вам не нужно выполнять приведение, потому что метод доступа вернет JToken:

foreach (JProperty x in obj["otherObject"]) { // Where 'obj' and 'obj["otherObject"]' are both JObjects
    string name = x.Name;
    JToken value = x.Value;
}
Даниэль
источник
3
Вы можете также удобно использовать LINQ следующим образом: obj.Properties().Select(p => p.Name + ": " + p.Value).
itslittlejohn 02
Это была именно та информация, которую я искал. Спасибо вам большое!
jhoepken
15

Ответ у меня не сработал. Я не знаю, как он получил столько голосов. Хотя это помогло мне указать направление.

Этот ответ сработал для меня:

foreach (var x in jobj)
{
    var key = ((JProperty) (x)).Name;
    var jvalue = ((JProperty)(x)).Value ;
}
jaxxbo
источник
1
При этом (после этой строки: JObject priceComplianceJson = JObject.Parse (File.ReadAllText (fullPath));) я получаю: «Невозможно преобразовать тип 'System.Collections.Generic.KeyValuePair <string, Newtonsoft.Json.Linq.JToken>' на 'Newtonsoft.Json.Linq.JProperty' "Однако удаление литья работает: var key = x.Key; var jvalue = x.Value; - по крайней мере компилируется ... Завтра накрою функциональность.
Б. Клей Шеннон
3

Для таких людей, как я, наркоманов linq и на основе ответа svick , здесь подход linq:

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

Теперь вы можете создавать выражения linq, например:

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

Или просто:

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

Или этот для перебора всех данных:

obj_linq.ToList().ForEach( x => { do stuff } ); 
Дани Эррера
источник