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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8855494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 04:49:08  来源:igfitidea点击:

How do I parse a JSON object in C# when I don't know the key in advance?

c#jsonjson.net

提问by Nathan DeWitt

I have some JSON data that looks like this:

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

How can I parse this using JSON.net? I can first do this:

如何使用 JSON.net 解析它?我可以先这样做:

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.

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

采纳答案by TrueWill

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

回答by Konstantin

Have you considered using JavascriptSerializer?

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

http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

回答by MethodMan

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

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

回答by Brian Rogers

You can iterate over the descendants with a simple LINQ query like this:

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

Similarly, if you want just the ref_idvalues, you can get those like this:

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

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

回答by Ryan Smyth

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.)

我发现 TrueWill 的答案有效,但我想避免 foreach 并尝试使用简单的 for 循环来提高速度。我的结果肯定是充其量只能被描述为丑陋的。以防万一它们对任何人都有用。(为了能够更容易地看到事情,我离开了 WriteLine。)

Note that this will not work for some JSON and isn't perfectly generic. Some null checks could be done better, etc.

请注意,这不适用于某些 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

回答by MangoBoy

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.

我正在使用 Json.NET 并编写了一种快速方法,您可以使用递归方法打印出所有键和相应的值。

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