当我没有';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"]);
}
但这当然行不通。如果您在编写代码时知道密钥,那么所有的示例都非常有效。当你事先不知道钥匙时,它就会坏掉。
这是可行的;这很管用,但并不优雅。我相信还有更好的方法。
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