当我没有';I don’我事先不知道钥匙

本文关键字:不知道 钥匙 don | 更新日期: 2023-09-27 18:20:26

我有一些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"]);
}

但这当然行不通。如果您在编写代码时知道密钥,那么所有的示例都非常有效。当你事先不知道钥匙时,它就会坏掉。

当我没有';I don’我事先不知道钥匙

这是可行的;这很管用,但并不优雅。我相信还有更好的方法。

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类型:asdf参考编号:7568id:910721类型:asdf参考编号:7568id:910723类型:asdfref_id:7568

您可以使用一个简单的LINQ查询来迭代子对象,如下所示:

JObject jFoo = JObject.Parse(json);
foreach (JObject obj in jFoo.Properties().Select(p => p.Value))
{
    Console.WriteLine("id: " + obj["id"]);
    Console.WriteLine("type: " + obj["type"]);
    Console.WriteLine("ref_id: " + obj["ref_id"]);
}

Fiddle:https://dotnetfiddle.net/fwINPa

或者,如果你只想要所有的ref_id值,你可以这样做:

string[] refIds = jFoo.Properties()
                      .Select(p => (string)p.Value["ref_id"])
                      .ToArray();
Console.Write(string.Join("'r'n", refIds));

Fiddle:https://dotnetfiddle.net/twOuVY

我使用的是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);
        }
    }

您是否考虑过使用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

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"]);
}

我发现TrueWill的答案有效,但为了速度起见,我想避免foreach,并尝试使用简单的for循环。我的结果充其量只能说是丑陋的。它们在这里,以防对任何人有用。(我离开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's 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