Как разобрать объект JSON на С#, если я заранее не знаю ключ?
У меня есть некоторые данные JSON, которые выглядят следующим образом:
{
"910719": {
"id": 910719,
"type": "asdf",
"ref_id": 7568
},
"910721": {
"id": 910721,
"type": "asdf",
"ref_id": 7568
},
"910723": {
"id": 910723,
"type": "asdf",
"ref_id": 7568
}
}
Как я могу разобрать это с помощью JSON.net? Сначала я могу это сделать:
JObject jFoo = JObject.Parse(data);
Мне нужно иметь возможность выполнять итерацию по каждому объекту в этом списке. Я хотел бы иметь возможность сделать что-то вроде этого:
foreach (string ref_id in (string)jFoo["ref_id"]) {...}
или
foreach (JToken t in jFoo.Descendants())
{
Console.WriteLine((string)t["ref_id"]);
}
но, конечно, это не сработает. Все примеры отлично работают, если вы знаете ключ при написании кода. Он ломается, когда вы заранее не знаете ключ.
Ответы
Ответ 1
Это выполнимо; это работает, но это не изящно. Я уверен, что есть лучший способ.
var o = JObject.Parse(yourJsonString);
foreach (JToken child in o.Children())
{
foreach (JToken grandChild in child)
{
foreach (JToken grandGrandChild in grandChild)
{
var property = grandGrandChild as JProperty;
if (property != null)
{
Console.WriteLine(property.Name + ":" + property.Value);
}
}
}
}
Печать
id:910719
type:asdf
ref_id:7568
id:910721
type:asdf
ref_id:7568
id:910723
type:asdf
ref_id:7568
Ответ 2
Вы можете перебирать потомков с помощью простого запроса LINQ следующим образом:
JObject jFoo = JObject.Parse(json);
foreach (JObject obj in jFoo.Properties().Select(p => p.Value))
{
Console.WriteLine("id: " + obj["id"]);
Console.WriteLine("ref_id: " + obj["ref_id"]);
}
Аналогично, если вы хотите только значения ref_id
, вы можете получить следующие значения:
foreach (string refId in jFoo.Properties().Select(p => p.Value["ref_id"]))
{
Console.WriteLine(refId);
}
Ответ 3
Я использую Json.NET, и я быстро написал, где вы можете распечатать все ключи и соответствующие значения с помощью рекурсивного метода.
var o = JObject.Parse(YourJsonString);
getAllProperties(o); //call our recursive method
Затем вы можете использовать этот рекурсивный метод для получения всех свойств и их значений
void getAllProperties(JToken children)
{
foreach (JToken child in children.Children())
{
var property = child as JProperty;
if (property != null)
{
Console.WriteLine(property.Name + " " + property.Value);//print all of the values
}
getAllProperties(child);
}
}
Ответ 4
Рассматривали ли вы использование JavascriptSerializer?
вы можете попробовать сделать что-то вроде этого:
JavaScriptSerializer serializer = new JavaScriptSerializer();
var foo = serializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(data);
foreach(var item in foo)
{
Console.Writeln(item.Value["ref_id"]);
}
http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx
Ответ 5
Решение Konstantin будет работать, но если вы хотите, чтобы список Id делал то же самое, а вместо Console.Writeln() использовал следующий
List<string> list = new List<string>();
JavaScriptSerializer serializer = new JavaScriptSerializer();
var foo = serializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(data);
foreach(var item in foo)
{
list.Add(item.Value["ref_id"]);
}
Ответ 6
Я нашел TrueWill ответ, но я хотел избежать foreach и попытаться получить простой цикл для работы ради скорости. Мои результаты были, безусловно, тем, что в лучшем случае можно было бы назвать уродливым. Здесь они на случай, если они полезны для всех. (Я ушел в WriteLine, чтобы уметь видеть вещи немного легче.)
Обратите внимание, что это не сработает для некоторых JSON и не является совершенно общим. Некоторые нулевые проверки могут быть выполнены лучше и т.д.
// NOW, DOING IT ALL AS A FOR LOOP...
// a, b, c, d - for iterator counters.
// j1, j2, j3, j4 - the JTokens to iterator over - each is a child of the previous
// p, q, r, s - The properties from j1/2/3/4.
JObject o = JObject.Parse(json);
JToken j1 = o.First;
for (int a = 0; a < o.Children().Count(); a++) { // Outermost loop gives us result, error, id.
if (j1 == null)
continue;
if (a > 0) {
j1 = j1.Next;
if (j1 == null)
continue;
}
var p = j1 as JProperty;
Console.WriteLine("FOR 0 = " + a.ToString() + " --- " + p.Name);
// DO STUFF HERE.
// FIRST INNER LOOP
// Set up a JToken or continue
JToken j2 = j1.Children().First() as JToken;
if (j1.Children().Count() > 0) {
j2 = j1.Children().First() as JToken;
} else {
continue;
}
Console.WriteLine("*** STARTING FIRST INNER...");
for (int b = 0; b < j1.Children().Count(); b++) { // returns nothing as second loop above.
if (j2 == null) {
Console.WriteLine("*** j2 null 1...");
continue;
}
if (b > 0) {
j2 = j2.Next;
if (j2 == null) {
Console.WriteLine("*** j2 null 2...");
continue;
}
}
var q = j2 as JProperty;
// These null checks need to be != or ==, depending on what needed.
if (q != null) {
Console.WriteLine("FOR 1 = " + a.ToString() + ","
+ b.ToString() + " --- " + q.Name);
// DO STUFF HERE.
// ...
} // q !null check
// SECOND INNER LOOP
// Set up a JToken or continue
JToken j3;
if (j2.Children().Count() > 0) {
j3 = j2.Children().First() as JToken;
} else {
continue;
}
Console.WriteLine("****** STARTING SECOND INNER...");
for (int c = 0; c < j2.Children().Count(); c++) {
if (j3 == null)
continue;
if (c > 0) {
j3 = j3.Next;
if (j3 == null)
continue;
}
var r = j3 as JProperty;
if (r == null) {
continue;
} // r null check
Console.WriteLine("FOR 2 = "
+ a.ToString() + ","
+ b.ToString() + ","
+ c.ToString() + " --- " + r.Name);
// DO STUFF HERE.
// THIRD INNER LOOP
// Set up a JToken or continue
JToken j4;
if (j3.Children().Count() > 0) {
j4 = j3.Children().First() as JToken;
} else {
continue;
}
Console.WriteLine("********* STARTING THIRD INNER...");
for (int d = 0; d < j3.Children().Count(); d++) {
if (j4 == null)
continue;
if (c > 0) {
j4 = j4.Next;
if (j4 == null)
continue;
}
var s = j4 as JProperty;
if (s == null) {
continue;
} // s null check
Console.WriteLine("FOR 3 = "
+ a.ToString() + ","
+ b.ToString() + ","
+ c.ToString() + ","
+ d.ToString() + " --- " + s.Name);
// DO STUFF HERE.
// ...
} // for d - j3
} // for c - j2
} // for b - j1
} // for a - original JObject