如果我事先不知道密钥,如何解析C#中的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"]); } 

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

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

 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
 REF_ID:7568
 ID:910721
类型:ASDF
 REF_ID:7568
 ID:910723
类型:ASDF
 REF_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("ref_id: " + obj["ref_id"]); } 

同样,如果你只想要ref_id值,你可以得到这样的:

 foreach (string refId in jFoo.Properties().Select(p => p.Value["ref_id"])) { Console.WriteLine(refId); } 

我正在使用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>>(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 list = new List(); JavaScriptSerializer serializer = new JavaScriptSerializer(); var foo = serializer.Deserialize>>(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