C# 使用 LINQ 查询 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12458302/
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 23:20:26  来源:igfitidea点击:

Query JSON using LINQ

c#.netjsonlinq

提问by KDee

I have a Json response that I receive from an API call. It has several nested levels as show below (this is a snippet):

我有一个从 API 调用中收到的 Json 响应。它有几个嵌套级别,如下所示(这是一个片段):

"Items": [
  {
    "Result": {
      "Id": "191e24b8-887d-e111-96ec-000c29128cee",
      "Name": "Name",
      "StartDate": "2012-04-03T00:00:00+01:00",
      "EndDate": null,
      "Status": {
        "Name": "Active",
        "Value": 5
      },
      "Client": {
        "Id": "35ea10da-b8d5-4ef8-bf23-c829ae90fe60",
        "Name": "client Name",
        "AdditionalItems": {}
      },
      "ServiceAgreement": {
        "Id": "65216699-a409-44b0-8294-0e995eb05d9d",
        "Name": "Name",
        "AdditionalItems": {
          "ScheduleBased": true,
          "PayFrequency": {
            "Id": "981acb72-8291-de11-98fa-005056c00008",
            "Name": "Weekly",
            "AdditionalItems": {}
          },
          "PayCycle": [
            {
              "Name": "Schedule Based",
              "ScheduleBased": true,
              "SelfBilling": false,
              "Id": "a8a2ecc4-ff79-46da-a135-743b57808ec3",
              "CreatedOn": "2011-09-16T23:32:19+01:00",
              "CreatedBy": "System Administrator",
              "ModifiedOn": "2011-09-16T23:32:19+01:00",
              "ModifiedBy": "System Administrator",
              "Archived": false
            }
          ]
        }
      },
}
]
...

What I want to do is retreive the data from the PayCycle node using Linq. I can for example get the items with a value of true using Result.ServiceAgreement.AdditionalItems.SchedultedBased using the following Linq in the Controller:

我想要做的是使用 Linq 从 PayCycle 节点检索数据。例如,我可以使用控制器中的以下 Linq 使用 Result.ServiceAgreement.AdditionalItems.ScheduultedBased 获取值为 true 的项目:

var result = from p in data["Data"]["Items"].Children()
             where (bool)p["Result"]["ServiceAgreement"]["AdditionalItems"]["ScheduleBased"] == true
             select new
             {
                 Name = (string)p["Result"]["Client"]["Name"],
                 Id = (string)p["Result"]["Client"]["Id"]
             };

Now I need to get Result.ServiceAgreement.AdditionalItems.Paycycle.ScheduleBasedand SelfBillingproperties. How do I do this if PayCycle is also an array, how do I get the children as I did with Data.Items in the Linq above so that I can have the where clause filter on both these items?

现在我需要获取Result.ServiceAgreement.AdditionalItems.Paycycle.ScheduleBasedSelfBilling属性。如果 PayCycle 也是一个数组,我该怎么做,我如何像在上面的 Linq 中处理 Data.Items 一样获取子项,以便我可以对这两个项目进行 where 子句过滤?

采纳答案by CodingWithSpike

You can deserialize the JSON into a dynamicobject, and then use Linq to Objects:

您可以将 JSON 反序列化为一个dynamic对象,然后使用 Linq to Objects:

    [TestMethod]
    public void TestMethod1()
    {
        const string json = @"""Items"": [
{
""Result"": {
  ""Id"": ""191e24b8-887d-e111-96ec-000c29128cee"",
  ""Name"": ""Name"",
  ""StartDate"": ""2012-04-03T00:00:00+01:00"",
  ""EndDate"": null,
  ""Status"": {
    ""Name"": ""Active"",
    ""Value"": 5
  },
  ""Client"": {
    ""Id"": ""35ea10da-b8d5-4ef8-bf23-c829ae90fe60"",
    ""Name"": ""client Name"",
    ""AdditionalItems"": {}
  },
  ""ServiceAgreement"": {
    ""Id"": ""65216699-a409-44b0-8294-0e995eb05d9d"",
    ""Name"": ""Name"",
    ""AdditionalItems"": {
      ""ScheduleBased"": true,
      ""PayFrequency"": {
        ""Id"": ""981acb72-8291-de11-98fa-005056c00008"",
        ""Name"": ""Weekly"",
        ""AdditionalItems"": {}
      },
      ""PayCycle"": [
        {
          ""Name"": ""Schedule Based"",
          ""ScheduleBased"": true,
          ""SelfBilling"": false,
          ""Id"": ""a8a2ecc4-ff79-46da-a135-743b57808ec3"",
          ""CreatedOn"": ""2011-09-16T23:32:19+01:00"",
          ""CreatedBy"": ""System Administrator"",
          ""ModifiedOn"": ""2011-09-16T23:32:19+01:00"",
          ""ModifiedBy"": ""System Administrator"",
          ""Archived"": false
        }
      ]
    }
  }
}
}
]";
        dynamic data = System.Web.Helpers.Json.Decode("{" + json + "}");

        var result = from i in (IEnumerable<dynamic>)data.Items
                     where i.Result.ServiceAgreement.AdditionalItems.ScheduleBased == true
                     select new
                            {
                                i.Result.Client.Name,
                                i.Result.Client.Id
                            };

        Assert.AreEqual(1, result.Count());
        Assert.AreEqual("client Name", result.First().Name);
        Assert.AreEqual("35ea10da-b8d5-4ef8-bf23-c829ae90fe60", result.First().Id);
    }

Note that I had to add brackets { and } around your example json string, or else the .NET json parser doesn't like it.

请注意,我必须在示例 json 字符串周围添加方括号 { 和 },否则 .NET json 解析器不喜欢它。

回答by Rohan Büchner

To start off, I'm not familiar with writing LINQ/LAMBDA using this format ["some"]["thing"]. My first step would be to create some classes/objects to house the data in to ease creating any code afterwards.

首先,我不熟悉使用这种格式 ["some"]["thing"] 编写 LINQ/LAMBDA。我的第一步是创建一些类/对象来存放数据,以便之后轻松创建任何代码。

e.g.

例如

public class Result
{
    public Guid Id { get; set; } 
    public string Name { get; set; },
    public DateTime StartDate  { get; set; }
    //you get the idea
}

But possibly try the following?

但可能尝试以下方法?

    var result = from p in data["Data"]["Items"].Children()
                 where (bool)p["Result"]["ServiceAgreement"]["AdditionalItems"]["ScheduleBased"] == true
                    && (p["Result"]["ServiceAgreement"]["AdditionalItems"]["PayCycle"]).Where(o => o.["ScheduleBased"] == true)
                 select new
                 {
                     Name = (string)p["Result"]["Client"]["Name"],
                     Id = (string)p["Result"]["Client"]["Id"]
                 };