Подтвердить что ты не робот

Как разобрать объект 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"]);
}

но, конечно, это не сработает. Все примеры отлично работают, если вы знаете ключ при написании кода. Он ломается, когда вы заранее не знаете ключ.

4b9b3361

Ответ 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