pandas.json_normalize() 专为解析嵌套JSON设计,自动跳过None、空列表等异常,支持record_path和meta参数灵活提取,避免手写递归的崩溃风险。

直接用 pandas.json_normalize(),别手写递归或链式 .get() —— 它专为这种场景设计,容错强、路径清晰、输出即用。
为什么 json_normalize() 比手写递归更省心
手写递归容易在中间层遇到 None 或 list 就崩:比如 data.get('a', {}).get('b', {}).get('c'),一旦 data['a'] 是 None 或 [],调用 .get() 就报 AttributeError 或 TypeError。而 json_normalize() 底层自动跳过缺失字段、空列表、None 值,只展开真实存在的结构。
-
record_path必须指向一个list,不是dict;否则报TypeError: unhashable type: 'dict' - 用
print(type(data.get('items')))先确认你要展开的字段类型 - 嵌套路径支持字符串(如
'results.data.items')或列表(如['results', 'data', 'items']),后者能避开键名含点号的问题 -
meta字段缺失时填NaN,不中断执行;但同名字段(如外层和内层都有id)会被后出现的覆盖,需用sep='_'避免冲突
遇到“看着像 JSON,但 json.loads() 直接炸”的情况怎么办
这不是嵌套问题,是数据本身不合法:单引号、尾逗号、JS 对象字面量、BOM 头、GBK 编码混入等。必须在 json_normalize() 之前处理干净。
- 先用
response.content.decode('utf-8-sig')去掉 UTF-8 BOM - 再用正则粗略清洗:把单引号换成双引号(
re.sub(r"(?),删尾逗号(re.sub(r",\s*}", "}", text)) - 最后才进
json.loads();如果仍失败,说明可能是 JS 对象字面量,改用ast.literal_eval()(仅限可信源) - 切记:
json_normalize()不处理原始字符串错误,它只在json.loads()成功后才工作
超深嵌套但不需要扁平化成表?用 jsonpath-ng 精准捞节点
当目标只是提取某几个深层字段(比如所有 $.store.book[*].author),而不是生成完整 DataFrame,jsonpath-ng 比遍历快得多,也比手写循环语义清晰。
- 安装:
pip install jsonpath-ng - 用法:
from jsonpath_ng import parse; from jsonpath_ng.ext import parse as ext_parse -
ext_parse("$.data..items[?(@.status=='active')].id").find(data)支持过滤、通配符、递归下降(..) - 注意:它不修复语法错误,输入必须是合法 Python dict/list;错误路径返回空列表,不会抛异常
真正难的从来不是“怎么展开”,而是“哪一层该展开、哪一层该保留、哪些字段要提前归一”。json_normalize() 给你的是结构化起点,后续筛选、去重、类型转换(比如把字符串时间转 pd.to_datetime())才是实际工作量所在。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











