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

如何在C#中用StreamReader读取JSON文件并跳过无效节点

解决方案:跳过大型JSON中的无效节点继续处理

问题场景

处理大型JSON数组时,部分节点存在格式错误(如示例中第一个对象"type": "message"后缺少逗号),需要跳过无效节点,继续处理后续有效内容,避免整个流程终止。

JSON示例:

[
  {
    "id": "a5db927f-62b3-4b30-b520-83cff902c3ef",
    "type": "message"
    "parent": null,
    "participant": "mauraans",
    "body": "We've moved the meeting out. Apologies for the last minute changes. Appears daylight savings time has caused challenges with time zones.",
    "conversation": "D04QU11BTJN",
    "importance": "normal",
    "timestamp": "1680541760.235769",
    "lastmodifiedtime": null,
    "deleted": false
  },
  {
    "id": "6db0169c-d8d9-4d27-8fa9-b60b9f163b87",
    "type": "message",
    "parent": null,
    "participant": "mauraans",
    "body": "What time did you have on your calendar and we'll go with that?",
    "conversation": "D04QU11BTJN",
    "importance": "normal",
    "timestamp": "1680539518.455199",
    "lastmodifiedtime": null,
    "deleted": false
  }
]

原代码问题

原代码在捕获JsonReaderException后直接调用reader.Skip(),但此时reader处于异常状态,无法正确识别当前节点的边界,Skip()无法准确定位到下一个有效节点,导致后续处理仍出错。

原代码:

using(FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) {
  using(BufferedStream bufferedStream = new BufferedStream(fs, 5000)) {
    using(StreamReader r = new StreamReader(bufferedStream))
    using(JsonTextReader reader = new JsonTextReader(r)) {
      JsonSerializer serializer = new JsonSerializer();

      while (reader.Read()) {
        try {
          if (reader.TokenType == JsonToken.StartObject) {
            var node = serializer.Deserialize < dynamic > (reader);
            Console.WriteLine(node.id);
            nodeCount++;
          }
        } catch (JsonReaderException ex) {
          reader.Skip();
        }
      }
    }
  }
}

修正后的代码

核心思路:捕获异常后,手动遍历token并跟踪对象嵌套层级,确保完整跳过整个无效对象,直到找到下一个有效节点或数组结尾。

int nodeCount = 0;
string filePath = "your-json-file-path.json";

using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (BufferedStream bufferedStream = new BufferedStream(fs, 5000))
using (StreamReader r = new StreamReader(bufferedStream))
using (JsonTextReader reader = new JsonTextReader(r))
{
    JsonSerializer serializer = new JsonSerializer();

    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            try
            {
                var node = serializer.Deserialize<dynamic>(reader);
                Console.WriteLine(node.id);
                nodeCount++;
            }
            catch (JsonReaderException)
            {
                // 手动跳过当前无效对象,处理嵌套层级
                int depth = 1;
                while (depth > 0 && reader.Read())
                {
                    if (reader.TokenType == JsonToken.StartObject)
                        depth++;
                    else if (reader.TokenType == JsonToken.EndObject)
                        depth--;
                }
                Console.WriteLine("跳过一个无效节点");
            }
        }
    }
}
Console.WriteLine($"共处理有效节点数:{nodeCount}");

关键说明

  • 异常捕获后通过depth变量跟踪对象嵌套层级,确保完整跳过整个无效对象,不会停留在中间位置。
  • 遍历token直到depth归0(找到当前对象的EndObject)或到达数组结尾,保证后续reader能正确定位到下一个有效节点。
  • 保持流式读取特性,适合处理大型JSON文件,不会将整个文件加载到内存中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:12:38