【问题标题】:Simple way of querying a JSON in C# using Json.NET使用 Json.NET 在 C# 中查询 JSON 的简单方法
【发布时间】:2021-07-15 07:57:05
【问题描述】:

查询JSON对象而不是编写多个foreachloops的简单方法是什么?

示例 JSON

{
    "result_index": 0,
    "results": [
       {
          "final": true,
          "alternatives": [
             {
                "delta": 0.9,
                "timestamps": [
                   [
                      "hi",
                      2.55,
                      2.81
                   ]
                ]
             }
          ]
       }
    ]
}

有没有办法将多个关注foreach 替换为单个foreach

var rawData = JObject.Parse(responseString);
var results = rawData["results"];

    foreach (var item in results)
     {
         foreach (var alternative in item["alternatives"])
          {
            foreach (var timestamp in alternative["timestamps"])
             {
                           
             }
          }
      }

【问题讨论】:

  • 正确反序列化,然后使用SelectMany
  • 目前我们不知道results 的类型,也不知道您使用的是哪个 JSON 库,因此很难给出具体答案。例如,Json.NET 支持 JSON 路径,这可能会对您有所帮助(请参阅 newtonsoft.com/json/help/html/QueryJsonSelectTokenWithLinq.htm),但我们不知道您是否使用 Json.NET...
  • @JonSkeet 是的,我正在使用 Json.NET
  • 对,所以请编辑问题以明确说明,最好提供minimal reproducible example

标签: c# json json.net


【解决方案1】:

对于 C# 或任何其他 .NET 语言,我建议您使用 Newtonsoft Library 的 Linq 功能。看看this example here

作为@JonSkeet 答案的更新,这里有一组工作代码。

class Program
    {
        static void Main(string[] args)
        {
            var sample = JsonConvert.DeserializeObject(File.ReadAllText("SampleJSON.json")) as JObject;

            var timestamps = (from item in sample["results"]
                              from alternative in item["alternatives"]
                              from timestamp in alternative["timestamps"] select timestamp)
                              .SelectMany(t => t);
            foreach(var ts in timestamps)
            {
                var working = ts.ToObject<string>() + " - Hello Ts";
            }

        }
    }

【讨论】:

  • 不是我的反对意见,但我怀疑这是因为答案基本上只是一个链接。如果您在答案中提供了一个代码示例,理想情况下可以准确显示 OP 如何更改其当前代码,那将是一个更好的答案。
  • 我很欣赏@JonSkeet 的观点,但是复制在实际使用产品的文档中清晰可见的代码有什么意义。
  • 因为 a) 链接坏了,b) 您可以提供针对 OP 的问题量身定制的答案 - 文档不能。这么说吧:想象您当前的答案与一个显示如何使用 LINQ 更改 OP 代码的答案并排。哪个是更好的答案? (我还不如自己做……)
  • 现在这是一个建设性的答案@JonSkeet,感谢您的澄清
【解决方案2】:

出现了两个选项。第一种是使用 LINQ - 您基本上希望在查询表达式中有多个 from 子句,或者调用 SelectMany。这是一个完整的例子:

using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        string json = File.ReadAllText("test.json");
        var rawData = JObject.Parse(json);
        var results = rawData["results"];

        var timestamps = from item in results
                         from alternative in item["alternatives"]
                         from timestampArray in alternative["timestamps"]
                         from timestamp in timestampArray
                         select timestamp;
        foreach (var timestamp in timestamps)
        {
            Console.WriteLine(timestamp);
        }
    }
}

输出:

hi
2.55
2.81

或者,您可以使用带有 SelectTokens 方法的 JSON 路径。这不是我以前使用过的东西,但以下查询有效 - 它可能不是最好的方法:

using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        string json = File.ReadAllText("test.json");
        var rawData = JObject.Parse(json);
        var timestamps = rawData.SelectTokens("$.results[*].alternatives[*].timestamps[*][*]");
        foreach (var timestamp in timestamps)
        {
            Console.WriteLine(timestamp);
        }
    }
}

【讨论】:

  • 感谢乔恩,但两者都不起作用。第一个抛出错误消息,第二个不迭代
  • @Aniruddha:“抛出错误消息”并没有给我任何真实的信息。提示:如果您像我之前建议的那样提供minimal reproducible example,我可以对其进行测试。更好的问题会带来更好的答案......(请注意,对于第二部分,我只说它会“类似于”JSON 路径查询 - 您应该对可能需要的路径表达式进行更多研究。)
  • 我已经编辑了问题并编写了我目前使用的代码。我得到的消息是查询语句后面应该跟select
  • 我已经用@JonSkeet 示例的工作示例更新了我的原始答案,希望这能让你得到排序。
  • @Aniruddha:这仍然不是真正的minimal reproducible example - 理想情况下,我应该能够复制、粘贴、编译和运行,而无需添加类包装器等。你应该尽量让它变得简单尽可能有人帮助你。肯定好多了,现在我要改变我的答案,所以它完整的......但请从中学习并在未来提出更好的问题。
猜你喜欢
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多