如何使用Newtonsoft查询嵌套JToken数组,获取按Severity降序的前10个对象
问题描述
我有一个由JToken对象组成的嵌套数组,目前只能返回所有Severity<3的问题,但我希望获取按Severity成员降序排列的前10个对象。现在我在访问内层数组时遇到了困难,能不能指导我用Newtonsoft查询数据实现这个需求?
示例数据
[ [ { "IssueOrderNumber": 1, "Description": "Exhaust fumes leaking into Parts department.", "Resolution": "Increased outbound ventilation in Service area.", "Severity": 1 } ], [ { "IssueOrderNumber": 1, "Description": "Houston, we have a problem.", "Resolution": "We are working on it.", "Severity": 1 }, { "IssueOrderNumber": 2, "Description": "We have issues with employee retention.", "Resolution": "We will start giving retention bonuses.", "Severity": 2 }, { "IssueOrderNumber": 3, "Description": "Increasing incidents of sexual harassment.", "Resolution": "Sexual harassment training is now doubled, and an independent investigator/arbitrator has been hired.", "Severity": 2 } ], [ { "IssueOrderNumber": 1, "Description": "Deal worksheet left unattended on salesperson's desk", "Resolution": "Salesperson required training hours doubled", "Severity": 2 }, { "IssueOrderNumber": 2, "Description": "PII left exposed for customers submitting inquiries over Web", "Resolution": "Web site reengineered to encrypt PII", "Severity": 2 }, { "IssueOrderNumber": 3, "Description": "A hacker exposed PII for sales staff and managerial staff over the Web.", "Resolution": "Web site was patched", "Severity": 1 } ] ]
现有代码
jArrIssues2 = JArray.Parse(strJArrIssues); for (int i = 0; i < jArrIssues2.Count; i++) { for (int j = 0; j < jArrIssues2[i].Count(); j++) { JObject iss = JObject.Parse(jArrIssues2[i][j].ToString()); JObject tmpObj = new JObject(); int intSev = (int)iss["Severity"]; string strDescr = (string)iss["Description"]; if (intSev < 3) // Currently, getting all Sev 1, 2 issues; // I'd rather get the top 10 issues ordered by severity { tmpObj.AddFirst(new JProperty("Description", strDescr)); tmpObj.Property("Description").AddAfterSelf(new JProperty("Severity", intSev)); jArrUltimate.Add(tmpObj); } } }
解决方案
可以利用LINQ结合Newtonsoft.Json的API简化操作,无需嵌套循环,直接完成扁平化、筛选、排序和取前10的操作:
JArray jArrIssues2 = JArray.Parse(strJArrIssues); // 扁平化嵌套数组,筛选Severity<3的项,按Severity降序排列,取前10 var topIssues = jArrIssues2 // 展开外层数组的所有内层数组,得到单个JToken对象集合 .SelectMany(innerArray => innerArray) // 转换为JObject方便属性访问 .Select(token => token as JObject) // 过滤有效项:非空且Severity<3 .Where(issue => issue != null && (int)issue["Severity"] < 3) // 按Severity降序排序,若需进一步排序可追加条件(如IssueOrderNumber) .OrderByDescending(issue => (int)issue["Severity"]) // 取前10个结果 .Take(10) // 构造仅包含目标属性的JObject .Select(issue => new JObject( new JProperty("Description", (string)issue["Description"]), new JProperty("Severity", (int)issue["Severity"]) )) // 转换为JArray .ToArray(); JArray jArrUltimate = new JArray(topIssues);
代码说明
SelectMany:直接扁平化嵌套数组,避免手动嵌套循环遍历内层元素。- 类型转换与筛选:将JToken转为JObject,过滤出符合
Severity<3的有效问题项。 - 排序与截取:通过
OrderByDescending实现降序排序,Take(10)直接获取前10个结果。 - 结果构造:按需保留
Description和Severity属性,最终组装成目标JArray。
这种写法比原始嵌套循环更简洁高效,也符合C#的LINQ编程风格。
内容的提问来源于stack exchange,提问作者Nosnetrom
相关产品推荐
相关产品推荐

