You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中使用Newtonsoft多条件筛选JSON并计算平均值问题

在C#中用Newtonsoft处理JSON数据的正确方案

问题分析

你遇到的核心问题是Newtonsoft JSONPath对复杂多条件组合的支持有限,且用Intersect合并筛选结果的思路不符合数据层级逻辑(区域和item是嵌套关系,而非平行集合),导致区域筛选空值、无法提取value。

修正方案:用LINQ to JSON分步处理

相比JSONPath,LINQ to JSON(基于JObject/JArray)更灵活,能清晰实现多层筛选逻辑,步骤如下:

1. 完整代码示例

先确保引用Newtonsoft.Json.Linq命名空间,然后按以下逻辑编写代码:

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

class Program
{
    static void Main()
    {
        // 替换为你的实际JSON字符串
        string jsonStr = @"
        {
            ""regions"": [
                {
                    ""area"": 1,
                    ""items"": [
                        { ""value"": 0.3, ""numbers"": [2, 2, 1, 1] },
                        { ""value"": 0.5, ""numbers"": [-2, 3, 0.5, 1] },
                        { ""value"": 0.2, ""numbers"": [1, 2, 1, 1] }
                    ]
                },
                {
                    ""area"": 2,
                    ""items"": [
                        { ""value"": 0.6, ""numbers"": [2, 0, 1, 1] }
                    ]
                }
            ]
        }";

        // 解析JSON
        JObject root = JObject.Parse(jsonStr);

        // 步骤1:筛选area=1的区域
        var targetRegions = root["regions"]?
            .Where(region => region["area"]?.Value<int>() == 1)
            .ToList();

        if (!targetRegions.Any())
        {
            Console.WriteLine("未找到area=1的区域");
            return;
        }

        // 步骤2:提取所有区域下的items,并筛选符合numbers条件的项
        var validItems = targetRegions
            .SelectMany(region => region["items"]?.Children<JObject>() ?? Enumerable.Empty<JObject>())
            .Where(item => {
                var numbers = item["numbers"]?.Values<double>().ToList();
                // 先判断numbers数组长度是否足够
                if (numbers == null || numbers.Count < 4) return false;
                // 逐一验证条件
                bool cond1 = numbers[0] == 2 || numbers[0] == -2;
                bool cond2 = numbers[1] > 1;
                bool cond3 = numbers[2] > 0;
                bool cond4 = numbers[3] == 1;
                return cond1 && cond2 && cond3 && cond4;
            })
            .ToList();

        // 步骤3:计算value的平均值
        if (validItems.Any())
        {
            double averageValue = validItems.Average(item => item["value"]?.Value<double>() ?? 0);
            Console.WriteLine($"符合条件的items的value平均值:{averageValue}"); // 预期输出0.4
        }
        else
        {
            Console.WriteLine("没有符合条件的items");
        }
    }
}

2. 方案优势

  • 解决区域筛选空值问题:用Where直接遍历regions数组,判断area字段值,避免JSONPath的语法歧义。
  • 支持复杂条件组合:通过LINQ的Where方法组合多条件,逻辑清晰,不受JSONPath的语法限制。
  • 直接提取并计算:从符合条件的JObject中直接提取value字段,用Average方法计算平均值,无需额外集合合并操作。

关于JSONPath的替代尝试(不推荐)

如果一定要用JSONPath,可结合LINQ分步执行:

  1. 先提取area=1的区域下的所有items:
    var allItemsInArea1 = root.SelectTokens("$..regions[?(@.area == 1)].items[*]");
    
  2. 再对这些items应用numbers条件:
    var validItems = allItemsInArea1.Where(item => 
        item.SelectToken("numbers[0]").Value<double>() is 2 or -2 &&
        item.SelectToken("numbers[1]").Value<double>() > 1 &&
        item.SelectToken("numbers[2]").Value<double>() > 0 &&
        item.SelectToken("numbers[3]").Value<double>() == 1
    );
    

本质还是依赖LINQ,单纯JSONPath难以实现复杂多条件组合。

总结

优先选择LINQ to JSON方案,它更直观、易调试,能完美覆盖你的多层筛选和计算需求,避免JSONPath的语法局限性。

内容的提问来源于stack exchange,提问作者BezqyczekPL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 13:46:17