
本文介绍使用 ijson 库对超大规模 JSON 文件进行内存友好的流式解析,精准提取指定数组(如 "BuildingsList")中的字段并写入 CSV,避免内存溢出,适用于 250GB+ 级别数据。
本文介绍使用 ijson 库对超大规模 json 文件进行内存友好的流式解析,精准提取指定数组(如 `"buildingslist"`)中的字段并写入 csv,避免内存溢出,适用于 250gb+ 级别数据。
处理数百 GB 级别的 JSON 文件时,传统 json.load() 或全量加载到 Pandas 的方式必然失败——内存耗尽、进程崩溃是常态。关键在于放弃“加载全部”,转向“按需逐项流式提取”。ijson 正是为此类场景设计的增量式 JSON 解析器,它不构建完整对象树,而是通过事件驱动方式遍历底层 JSON token,从而实现常量级内存占用(通常仅几 MB)。
✅ 正确用法:精准定位 + 零缓冲逐行写入
原始代码存在两个致命问题:
使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。
- ijson.items(input_file, "BuildingsList") 返回的是整个 BuildingsList 数组(即一个巨大列表),仍会尝试一次性构造该结构,违背流式初衷;
- 手动维护 rows_buffer 并设置百万级缓冲区,不仅冗余,反而增加内存压力和逻辑复杂度。
正确做法是使用 "BuildingsList.item" 作为 prefix —— 这告诉 ijson 直接迭代数组中的每一个对象(即每个 building),跳过父容器解析:
import ijson
import csv
input_file_path = '/path/to/large_file.json'
output_file_path = '/path/to/output.csv'
# 明确指定需保留的字段(大小写需与 JSON 中完全一致)
desired_fieldnames = ["ID", "localityCode", "Coordinates", "BuildingType", "RentalStatus"]
with open(input_file_path, 'rb') as input_file, \
open(output_file_path, 'w', newline='', encoding='utf-8') as output_file:
writer = csv.DictWriter(
output_file,
fieldnames=desired_fieldnames,
extrasaction="ignore" # 自动忽略 JSON 中不存在的字段,避免 KeyError
)
writer.writeheader()
# 关键:使用 "BuildingsList.item" 逐个获取 building 对象
for building in ijson.items(input_file, "BuildingsList.item"):
# 直接写入,无需中间缓冲或字典重构
writer.writerow(building)? 为什么 "BuildingsList.item" 有效?
ijson 的 prefix 语法中,.item 表示“数组中每个元素”。若 JSON 结构为 {"BuildingsList": [{...}, {...}]},则 "BuildingsList.item" 会依次 yield 每个 {...} 对象,完全绕过将整个数组载入内存。
⚠️ 注意事项与最佳实践
- 字段名严格匹配:JSON 中的键名(如 "LocalityCode" vs "localityCode")必须与 desired_fieldnames 完全一致;建议先用小样本校验实际字段大小写。
- 编码与二进制模式:输入文件必须以 'rb' 模式打开(ijson 要求),输出 CSV 使用 encoding='utf-8' 并指定 newline=''(防止 Windows 下空行)。
-
缺失字段处理:extrasaction="ignore" 可安全跳过 JSON 中缺失的字段;若需默认值(如空字符串),可改用:
row = {k: building.get(k, "") for k in desired_fieldnames} writer.writerow(row) -
性能优化建议:
- 使用 SSD 存储输入/输出文件,I/O 是主要瓶颈;
- 若字段极少且结构固定,考虑用 ijson.parse() + 手动状态机进一步精简(但 items() 已足够简洁);
- 避免在循环内重复打开/关闭文件或创建 writer 实例。
✅ 总结
处理 TB 级 JSON 的核心原则是:让解析器只看见你真正需要的那一小片数据。ijson.items(file, "ArrayName.item") 是解锁这一能力的最简接口。它不依赖内存容量,只依赖磁盘吞吐与 CPU,可稳定运行数天完成 250GB+ 文件转换。记住——不是“如何更快地加载”,而是“如何根本不加载”。

















