【问题标题】:How to query into a JSON getting using LINQ?如何使用 LINQ 查询 JSON?
【发布时间】:2018-10-03 09:19:10
【问题描述】:

JSON

{
  "count": 3,
  "value": [
    {
      "id": "AAAAAAAAAAAAA",
      "description": "test1",
      "name": "name1"
    },
    {
      "id": "BBBBBBBBBB",
      "description": "test2",
      "name": "name2"
    },
    {
      "id": "CCCCCCCCCCCC",
      "description": "test3",
      "name": "name3"
    }
  ]
}

我的解决方案中有一个从 LIST api 检索并提供上面 JSON 的代码。 如何使用 LINQ 检索特定值? (例如)我需要选择name1,我会得到id,description,name 值。

我在我的代码中使用了dynamic 变量:

dynamic json = JObject.Parse(client.GetString().Result);

在过去的几个小时里,我一直在修改其他在线指南。但是,无法得到正确的结果。

请帮忙。

【问题讨论】:

  • 你为什么在这里使用dynamic?既然您已经知道 JSON 的结构,那么您应该为它创建一个类型。
  • 我使用动态来缩短代码行并使用核心。但我对此还是陌生的。我只会使用一次值,CMIIW,所以我认为制作另一个对象不好?
  • 我从未见过任何人使用dynamic 缩短代码行
  • @Hexxed :是的,在这种情况下你不应该使用dynamic,并在这里创建一个合适的类型。对于像 C# 这样的强类型语言,这就是要走的路。在语言中添加dynamic 背后的基本原理是允许调用可能返回不确定的结构/类型,例如对外部 DLL/COM 事物的调用。只有当你真的被卡住时才想使用它。
  • 我同意@Pac0,这里没有必要使用动态,因为你已经知道了json字符串的结构。除非您有充分的理由这样做,否则不要使用动态。检查Advantages and Disadvantages of C# 4.0 'dynamic' keyword?

标签: c# json linq asp.net-core linq-to-json


【解决方案1】:

一种解决方案是将 JSON 字符串反序列化为 C# 对象,然后使用 Linq 获取特定对象。

C# 类定义:

public class Content
{
    [JsonProperty("count")]
    public int Count { get; set; }

    [JsonProperty("value")]
    public List<Value> Values { get; set; }

    public Content()
    {
        Values = new List<Value>();
    }
}

public class Value
{
    [JsonProperty("id")]
    public string Id { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

反序列化并获取对象:

string json = @"{
""count"": 3,
""value"": [
  {
    ""id"": ""AAAAAAAAAAAAA"",
    ""description"": ""test1"",
    ""name"": ""name1""
  },
  {
    ""id"": ""BBBBBBBBBB"",
    ""description"": ""test2"",
    ""name"": ""name2""
  },
  {
    ""id"": ""CCCCCCCCCCCC"",
    ""description"": ""test3"",
    ""name"": ""name3""
  }
]
}";


Content content = JsonConvert.DeserializeObject<Content>(json);

Value value = content.Values.FirstOrDefault(x => x.Name.Equals("name1", StringComparison.InvariantCultureIgnoreCase));

【讨论】:

【解决方案2】:

首先,你可以创建一个类来代表一个客户:

public class Client
{
    public string Id { get; set; }
    public string Description { get; set; }
    public string Name { get; set; }
}

有了这个类,你可以使用JObject.Parse(正如你已经在做的那样)将JSON解析成可以查询的东西,使用SelectToken提取value数组,然后使用ToObject将其转换为Clients 的列表。看起来是这样的:

var jsonObject = JObject.Parse(json_source);
var jsonObjectValue = jsonObject.SelectToken("value");
var clients = jsonObjectValue.ToObject<List<Client>>();

获得clients 变量后,您可以使用简单的LINQ 语句查找name1

var clientWithName1 = clients.SingleOrDefault(x => x.Name == "name1");

在这种情况下,如果没有找到这样的客户端,clientWithName 将是 null

这是一个dotnetfiddle,它演示了一个完整的解决方案。

【讨论】:

  • 我更喜欢这个解决方案。只需添加我的两分钱: jsonObject["value"] 已经是一个 JArray,所以我们可以保存一个变量,结果是:var jsonObject = JObject.Parse(json_source); var clients = (jsonObject["value"]).ToObject&lt;List&lt;Client&gt;&gt;();
  • 感谢@WalterAgile 的输入。你甚至可以做到这一点:var clients = JObject.Parse(json_source)["value"].ToObject&lt;List&lt;Client&gt;&gt;();。 :)
【解决方案3】:

创建一个具有属性 id、description 和 name 的对象 Client。将 json 反序列化为这些对象的列表。

List<Client> clients = JsonConvert.Deserialize<List<Client>>(json_source);
string desc = clients[0].description;

【讨论】:

  • 然后clients.First[OrDefault](c =&gt; c.name == "name1");
  • @KirkLarkin 没错,它应该是一个包含客户列表的对象,如 RuiJarimba 的回答中所写。尽管如此,反序列化为适当类型而不是 dynamic 的想法还是让以后使用 Linq 变得更容易
  • 这不是正确的答案——你不能假设name1 的对象总是数组中的第一个,你需要查询反序列化的数组,正如@Rafalon 已经提到的那样
【解决方案4】:

显然,通过摆弄我的代码,我为自己找到了答案。 感谢那些试图帮助我给我想法的人。

var requestWorkProcess = await client.GetStringAsync("my url");
var workProcessId = JObject.Parse(requestWorkProcess)["value"].Children<JObject>().FirstOrDefault(o => o["name"].ToString() == workProcess).GetValue("id");

【讨论】:

  • 不是反对者,但这个答案不是推荐的方式。看来你正在尽你所能来规避语言提供的任何类型安全性。
猜你喜欢
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多