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

如何快速移除System.Text.Json.Nodes.JsonArray中符合条件的数百元素?

问题描述

如何以最快方式移除System.Text.Json.Nodes.JsonArray中符合特定条件的数百个元素?我有一个包含数百个元素的JsonArray,多数是无效数据,只需要保留符合指定条件的元素。是否能实现类似以下代码的操作?

jsonArray.RemoveAll(e => /* 任意条件 */)

我要最快的解决方案,不局限于JsonArray,也可以用更合适的替代方案。

更新内容:JSON文件示例

[{
    "timestamp":"2023-03-13T15:21:24.057Z",
    "type":"Gateway",
    "mac":"AC233FC0F654",
    "gatewayFree":23,
    "gatewayLoad":0.39000000000000001
},
{
    "timestamp":"2023-03-13T15:21:24.057Z",
    "type":"Unknown",
    "mac":"157007098D2E",
    "bleNo":0,
    "bleName":"",
    "rssi":-67,
    "rawData":"02011A07FF4C0015020034"
},
{
    "timestamp":"2023-03-13T15:21:24.058Z",
    "type":"Unknown",
    "mac":"147D21B57EB9",
    "bleNo":0,
    "bleName":"",
    "rssi":-78,
    "rawData":"0201060309536B16FF53500004F6400201020304FBE705060708040102FF"
}]

方案1:基于JsonArray的过滤实现

JsonArray没有内置RemoveAll方法,但可以通过两种方式实现需求:

新建过滤后的JsonArray(简洁优先)

直接通过LINQ筛选符合条件的元素,创建新数组,代码简洁易维护:

using System.Text.Json.Nodes;

// 假设jsonArray为已加载的目标数组
var filteredArray = new JsonArray(
    jsonArray.Where(node => node["type"]?.GetValue<string>() == "Gateway").ToArray()
);
  • 优势:代码简洁,避免原地修改的索引错乱问题
  • 劣势:会创建新数组,占用少量额外内存(数百级元素可忽略)

原地反向遍历删除(内存优先)

如果需要原地修改、避免额外内存占用,可反向遍历删除元素(正向遍历会因元素移除导致索引偏移):

for (int i = jsonArray.Count - 1; i >= 0; i--)
{
    var node = jsonArray[i];
    if (node["type"]?.GetValue<string>() != "Gateway")
    {
        jsonArray.RemoveAt(i);
    }
}
  • 优势:无额外内存开销
  • 劣势:代码稍繁琐,仅适合必须原地修改的场景

方案2:强类型集合过滤(性能最优)

如果JSON结构固定,反序列化为强类型List<T>后过滤是性能最高的方案,强类型操作比动态节点访问更快。

步骤1:定义对应实体类

public class DeviceData
{
    public DateTime Timestamp { get; set; }
    public string Type { get; set; }
    public string Mac { get; set; }
    public int? GatewayFree { get; set; }
    public double? GatewayLoad { get; set; }
    public int? BleNo { get; set; }
    public string BleName { get; set; }
    public int? Rssi { get; set; }
    public string RawData { get; set; }
}

步骤2:反序列化+过滤

using System.Text.Json;

// 从JSON字符串反序列化
var deviceList = JsonSerializer.Deserialize<List<DeviceData>>(jsonString);
// 过滤保留符合条件的元素
var filteredList = deviceList.Where(d => d.Type == "Gateway").ToList();

// 如需转回JsonArray
var filteredArray = JsonSerializer.SerializeToNode(filteredList) as JsonArray;
  • 优势:性能最优,类型安全,代码可读性强
  • 劣势:需要提前定义实体类,仅适合结构固定的JSON

方案3:JsonDocument流式处理(内存友好)

如果JSON文件规模远超数百级元素,用JsonDocument流式读取过滤,避免一次性加载整个文档到内存:

using System.Text.Json;

using var doc = JsonDocument.Parse(jsonString);
var filteredElements = new List<JsonElement>();

foreach (var element in doc.RootElement.EnumerateArray())
{
    if (element.TryGetProperty("type", out var typeProp) && typeProp.GetString() == "Gateway")
    {
        filteredElements.Add(element.Clone()); // 必须Clone,否则文档释放后元素失效
    }
}

// 转回JsonArray或直接序列化输出
var filteredJson = JsonSerializer.Serialize(filteredElements);
var filteredArray = JsonSerializer.Deserialize<JsonArray>(filteredJson);
  • 优势:内存占用极低,适合超大JSON文件
  • 劣势:代码稍复杂,数百级元素场景下没必要使用

性能对比

  • 数百级元素:**方案2(强类型过滤)**性能最优,其次是方案1的新建数组,最后是原地删除
  • 超大文件:方案3为最优选择

内容的提问来源于stack exchange,提问作者A. Wheatman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 22:15:20