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

解析多JSON文件时字符索引不一致问题及正确解析方案咨询

问题:解析逗号分隔的多行JSON对象时后续对象失败的原因与解决方法

我用以下Python代码解析存储在.json文件里的逗号分隔多行JSON对象(数据来自网页抓取):

import json

def stream_read_json(fn):
    start_pos = 0
    with open(fn, 'r', encoding='utf-8') as f:
        while True:
            try:
                obj = json.load(f)
                yield obj
                return
            except json.JSONDecodeError as e:
                f.seek(start_pos)
                json_str = f.read(e.pos)
                obj = json.loads(json_str, encoding = 'utf-8')
                start_pos += e.pos
                yield obj

第一个对象可正常解析,但后续对象无法解析。调试时发现,JSONDecodeError抛出的e.pos与IDE中选中的JSON对象结束位置的字符索引存在差异,测试时第二个JSON对象对应的f.seek(start_pos)值与报错的e.pos差异明显。以下是示例JSON:

{
  "user": {
    "id": 1,
    "profile": {
      "name": "Alice",
      "age": 30
    }
  },
  "product": {
    "sku": "A1234",
    "details": {
      "name": "Laptop",
      "price": 999.99
    }
  }
},
{
  "user": {
    "id": 2,
    "profile": {
      "name": "Bob",
      "age": 22
    }
  },
  "product": {
    "sku": "A123w",
    "details": {
      "name": "Laptop",
      "price": 9.99
    }
  }
}

差异产生的原因

  • 字节位置与字符索引不匹配:json.load()内部会处理换行符(比如将Windows的\r\n转为\n),但文件的seek操作是按字节位置计算的,而IDE显示的字符索引是按文本字符数统计的,换行符的字节长度差异会导致两者数值不一致。
  • 解析位置逻辑错误:e.pos是json.load()尝试解析时的错误位置(基于它的内部缓冲区),并非文件的实际字节位置。你用f.seek(start_pos)后读取e.pos个字符,会导致start_pos累加错误,后续读取的起始位置完全偏离。
  • 未处理分隔逗号:第一个JSON对象解析完成后,文件中剩余的逗号和换行符没有被跳过,后续解析从逗号开始,直接触发JSONDecodeError。

正确解析的解决方法

方法1:逐行缓存+raw_decode精准解析

使用json.JSONDecoder().raw_decode()方法,它会返回解析后的对象和解析到的索引位置,能准确截取剩余内容并跳过分隔符:

import json

def stream_read_json(fn):
    with open(fn, 'r', encoding='utf-8') as f:
        buffer = ''
        for line in f:
            buffer += line.strip()
            try:
                # 解析buffer中的第一个完整JSON对象,返回对象和结束索引
                obj, end_idx = json.JSONDecoder().raw_decode(buffer)
                yield obj
                # 移除已解析的部分,跳过逗号和空白字符
                buffer = buffer[end_idx:].lstrip(', \n\r')
            except json.JSONDecodeError:
                # 内容不完整,继续读取下一行
                continue

方法2:转换为JSON数组批量解析

如果文件体积不大,直接给内容包裹成JSON数组,利用标准JSON解析逻辑一次性处理:

import json

def read_json_objects(fn):
    with open(fn, 'r', encoding='utf-8') as f:
        content = f.read().strip()
        # 将逗号分隔的对象转为合法的JSON数组
        json_array = f'[{content}]'
        objects = json.loads(json_array)
        for obj in objects:
            yield obj

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:32:45