
本文介绍如何正确处理以换行分隔的多个 json 对象(json lines 格式)——这类文件常见于大数据导出场景,不能直接用 ijson 或 json.load() 解析,需逐行读取并单独解析。
本文介绍如何正确处理以换行分隔的多个 json 对象(json lines 格式)——这类文件常见于大数据导出场景,不能直接用 ijson 或 json.load() 解析,需逐行读取并单独解析。
你遇到的“trailing garbage”错误,并非代码或 ijson 使用不当,而是文件格式本身不符合 JSON 规范。你下载的 Kaggle 数据集(US Job Postings)实际采用的是 JSON Lines(也称 NDJSON)格式:每行是一个独立、合法的 JSON 对象,但整个文件不是一个 JSON 数组或单个 JSON 值。因此:
- ijson.items(f, 'item') 试图在单个 JSON 文档中查找路径为 "item" 的元素,但文件开头就是 {...},没有顶层键 item,且第二行立即出现新 {,被解析器视为非法残留内容;
- 即使启用 multiple_items=True,ijson 仍期望流式 JSON 结构(如 [{},{},...] 或 {"items":[{},{}]} ),而纯换行分隔的文本不满足其语法预期。
✅ 正确解法:放弃流式 JSON 解析器,改用逐行 + 内置 json.loads(),兼顾简洁性、内存效率与可靠性:
import json
# 推荐:使用 utf-8 编码(Kaggle 数据通常为 UTF-8),并添加基础异常处理
with open('file.json', 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
if not line: # 跳过空行
continue
try:
obj = json.loads(line)
# ✅ 此时 obj 是一个完整的 dict,可直接访问字段,例如:
# print(obj.get('_id', {}).get('$oid', 'N/A'))
except json.JSONDecodeError as e:
print(f"JSON 解析失败(第 {line_num} 行): {e} → '{line[:50]}...'")
continue # 或根据需求记录/跳过错误行⚠️ 注意事项:
- 不要用 'rb' 模式配合 json.loads():json.loads() 接收字符串,open(..., 'rb') 返回字节流,需先 .decode(),易引入编码错误;直接 'r' + encoding='utf-8' 更安全;
- 避免 ijson 误用:ijson 专为单个大型 JSON 文档(如嵌套很深的数组/对象)的增量解析设计,不适用于 JSON Lines;
- 内存友好性:上述方案内存占用恒定(≈ 单行 JSON 大小),3GB 文件可轻松处理;
- 扩展建议:若需进一步加速,可用 orjson 替代 json(需 pip install orjson),它解析速度通常快 3–5 倍且默认支持 UTF-8:
import orjson
with open('file.json', 'rb') as f: # orjson 接受 bytes,故可用 'rb'
for line in f:
line = line.strip()
if line:
try:
obj = orjson.loads(line) # 返回 bytes → dict,无编码歧义
except orjson.JSONDecodeError:
pass总结:识别文件真实格式是高效处理大数据的前提。面对 JSON Lines,应拥抱其设计哲学——“一行一对象”,用最简方法(for line in file + json.loads)实现稳定、低开销的流式处理。

















