如果我事先不知道密钥,如何解析C#中的JSON对象?

时间:2012-01-13 18:38:30

标签: c# json json.net

我有一些看起来像这样的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"]);
}

但当然不起作用。如果您在编写代码时知道密钥,那么所有示例都能很好地工作。如果您事先不知道密钥,它就会崩溃。

6 个答案:

答案 0 :(得分:21)

这是可行的;这可行,但它并不优雅。我确信有更好的方法。

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

答案 1 :(得分:3)

您可以使用简单的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);
}

答案 2 :(得分: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);
        }
    }

答案 3 :(得分:1)

你考虑过使用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

答案 4 :(得分:-1)

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

答案 5 :(得分:-2)

我发现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