处理大规模json文件应避免json.load()导致内存溢出,优先采用ijson迭代解析:json lines格式逐行loads;巨型数组用ijson.items(f, 'item');嵌套结构指定路径如'data.items.item';须二进制模式打开文件,注意路径大小写及字段缺失防护。

直接用 json.load() 读取大规模 JSON 文件,很容易触发内存溢出。迭代器方式的核心是“不加载全部,只拿当前需要的”,让程序始终只驻留少量数据。
识别文件结构再选方法
不是所有大 JSON 都适合同一种迭代解析方式,先看清楚格式:
- 如果文件是每行一个完整 JSON 对象(即 JSON Lines 或 .jsonl 格式),直接逐行读 +
json.loads()最快最稳 - 如果是一个巨型数组,例如
[{"id":1}, {"id":2}, ...],用ijson.items(f, 'item')流式取每个元素 - 如果是深层嵌套对象(如
{"data": {"items": [...]}}),需配合路径表达式,比如ijson.items(f, 'data.items.item')
用 ijson.items 精准提取数组项
这是最常用也最直观的迭代方式。它跳过解析整个文档的开销,只定位到目标数组并逐个 yield 元素:
- 确保以二进制模式打开文件:
open('data.json', 'rb'),ijson 内部依赖字节流 - 路径字符串要严格匹配结构,比如数组字段叫
results,就写'results.item';若数组在根层级,且名字就是item,才用'item' - 每个
item是已解析好的 Python 字典或列表,可直接访问键,无需再调json.loads
用 ijson.parse 做细粒度事件控制
当需要跳过大量无关字段、或处理不规则结构时,ijson.parse() 提供底层事件流:
- 返回三元组
(prefix, event, value),例如('users.0.name', 'string', 'Alice') - 通过判断
prefix和event类型(如'start_map'、'end_array')来跟踪解析位置 - 适合实现自定义状态机,比如只收集某个子路径下的所有数字字段,或统计某类对象出现次数
避免常见陷阱
迭代器虽轻量,但几个细节不注意仍会出错:
- 别用文本模式(
'r')打开文件传给 ijson —— 会报TypeError: a bytes-like object is required - 路径表达式区分大小写和下划线,
'Items'和'items'是不同字段 - 遇到缺失字段时,建议用
.get('key', default)而非直接['key'],防止KeyError - 若数据含非法字符或编码问题,提前加
encoding='utf-8'并捕获UnicodeDecodeError











