问题
I have some JSON data that looks like this:
{
"910719": {
"id": 910719,
"type": "asdf",
"ref_id": 7568
},
"910721": {
"id": 910721,
"type": "asdf",
"ref_id": 7568
},
"910723": {
"id": 910723,
"type": "asdf",
"ref_id": 7568
}
}
How can I parse this using JSON.net? I can first do this:
JObject jFoo = JObject.Parse(data);
I need to be able to iterate over each object in this list. I would like to be able to do something like this:
foreach (string ref_id in (string)jFoo["ref_id"]) {...}
or
foreach (JToken t in jFoo.Descendants())
{
Console.WriteLine((string)t["ref_id"]);
}
but of course that doesn't work. All the examples work great if you know the key while writing your code. It breaks down when you don't know the key in advance.
回答1:
It's doable; this works but it's not elegant. I'm sure there's a better way.
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);
}
}
}
}
Prints:
id:910719 type:asdf ref_id:7568 id:910721 type:asdf ref_id:7568 id:910723 type:asdf ref_id:7568
回答2:
You can iterate over the descendants with a simple LINQ query like this:
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"]);
}
Similarly, if you want just the ref_id
values, you can get those like this:
foreach (string refId in jFoo.Properties().Select(p => p.Value["ref_id"]))
{
Console.WriteLine(refId);
}
回答3:
I'm using Json.NET and I wrote a quick way where you can print out all of the keys and corresponding values using a recursive method.
var o = JObject.Parse(YourJsonString);
getAllProperties(o); //call our recursive method
Then you can use this recursive method to get all the Properties and their values
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:
Have you considered using JavascriptSerializer?
you could try do something like this:
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's solution will work but if you want a list of Id's do the same thing and instead of the Console.Writeln() use the following
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:
I found TrueWill's answer worked, but I wanted to avoid foreach and try getting a simple for loop to work for the sake of speed. My results were certainly what could be described as ugly at best. Here they are in case they are useful for anyone. (I've left in WriteLine for the sake of being able to see things a bit easier.)
Note that this will not work for some JSON and isn't perfectly generic. Some null checks could be done better, etc.
// 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
来源:https://stackoverflow.com/questions/8855494/how-do-i-parse-a-json-object-in-c-sharp-when-i-dont-know-the-key-in-advance