如何在C#中分步过滤JSON数组并获取指定属性关联详情?
问题
我有一个多层结构的JSON数组(示例如下),需要分两步过滤:
- 按顶级属性
env(例如值为ENG)筛选,得到对应环境的完整数据; - 在第一步的结果中,按子对象的
Id或Name属性(例如Name=TestA)筛选,获取对应的完整详情对象。
请问在C#中实现该需求的最佳方式是什么?
示例JSON数组:
[ { "env": "ENG", "details": [ { "Id": 3, "Name": "TestA", "programs": [ { "name": "TestA", "type": "AA" } ] }, { "tenantId": 5, "tenantName": "Demo", "programs": [ { "name": "DEMO", "type": "BB" }, { "name": "DEMO2", "type": "BB" } ] } ] }, { "env": "Span", "details": [ { "tenantId": 4, "tenantName": "Cat", "programs": [ { "name": "CAT", "type": "123" } ] }, { "tenantId": 5, "tenantName": "Demo", "programs": [ { "name": "DEMOSpan", "type": "www" }, { "name": "DEMOU2", "type": "eee" } ] } ] } ]
第一步筛选预期结果:
{ "env": "ENG", "details": [ { "Id": 3, "Name": "TestA", "programs": [ { "name": "TestA", "type": "AA" } ] }, { "tenantId": 5, "tenantName": "Demo", "programs": [ { "name": "DEMO", "type": "BB" }, { "name": "DEMO2", "type": "BB" } ] } ] }
第二步筛选预期结果:
{ "Id": 3, "Name": "TestA", "programs": [ { "name": "TestA", "type": "AA" } ] }
解决方案
在C#中,推荐两种实现方式,可根据场景选择:
方式一:强类型模型解析(推荐,类型安全)
先根据JSON结构定义对应实体类,再用System.Text.Json(.NET Core 3.0+内置)或Newtonsoft.Json完成序列化与筛选,这种方式能获得编译时类型检查,降低运行时错误。
1. 定义实体类
// 顶级环境数据对象 public class EnvData { public string Env { get; set; } public List<DetailItem> Details { get; set; } } // 详情子对象(部分属性为可选,需用可空类型) public class DetailItem { public int? Id { get; set; } public string Name { get; set; } public int? TenantId { get; set; } public string TenantName { get; set; } public List<Program> Programs { get; set; } } // 程序子对象 public class Program { public string Name { get; set; } public string Type { get; set; } }
2. 实现筛选逻辑
以System.Text.Json为例:
using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; class Program { static void Main() { string jsonStr = "你的JSON字符串内容"; // 反序列化为强类型列表 var envDataList = JsonSerializer.Deserialize<List<EnvData>>(jsonStr); // 第一步:按env筛选目标环境数据 var targetEnvData = envDataList.FirstOrDefault(data => data.Env.Equals("ENG", StringComparison.OrdinalIgnoreCase)); if (targetEnvData == null) { Console.WriteLine("未找到指定环境的数据"); return; } // 第二步:按Id或Name筛选目标详情项 var targetDetail = targetEnvData.Details.FirstOrDefault(item => item.Id == 3 || item.Name?.Equals("TestA", StringComparison.OrdinalIgnoreCase) == true); if (targetDetail != null) { // 输出格式化后的结果 string resultJson = JsonSerializer.Serialize(targetDetail, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine(resultJson); } else { Console.WriteLine("未找到指定的详情项"); } } }
方式二:动态类型/JObject解析(无需定义实体类,快速处理)
如果是临时脚本或快速验证场景,可直接用Newtonsoft.Json的JObject动态处理,无需提前定义实体类:
using Newtonsoft.Json.Linq; using System; using System.Linq; class Program { static void Main() { string jsonStr = "你的JSON字符串内容"; // 解析为JArray var jsonArray = JArray.Parse(jsonStr); // 第一步:筛选env为ENG的对象 var targetEnvObj = jsonArray.FirstOrDefault(obj => obj["env"]?.ToString().Equals("ENG", StringComparison.OrdinalIgnoreCase) == true); if (targetEnvObj == null) { Console.WriteLine("未找到指定环境的数据"); return; } // 第二步:筛选Name为TestA或Id为3的详情项 var detailsArray = targetEnvObj["details"] as JArray; var targetDetail = detailsArray.FirstOrDefault(item => item["Id"]?.Value<int>() == 3 || item["Name"]?.ToString().Equals("TestA", StringComparison.OrdinalIgnoreCase) == true); if (targetDetail != null) { Console.WriteLine(targetDetail.ToString(Newtonsoft.Json.Formatting.Indented)); } else { Console.WriteLine("未找到指定的详情项"); } } }
注意事项
- 强类型方式适合长期维护的项目,能避免拼写错误和类型不匹配问题;
- 动态类型方式适合快速验证,但缺少类型安全,需注意空值判断避免空引用异常;
- 筛选时可根据需求选择是否忽略大小写,示例中用
StringComparison.OrdinalIgnoreCase实现忽略大小写匹配。
内容的提问来源于stack exchange,提问作者David Andrews
相关产品推荐
相关产品推荐

