pandas.json_normalize() 专门用于展平嵌套JSON,通过record_path提取记录列表,meta提升父级字段,sep自定义分隔符;需要处理缺失字段、列表爆炸、性能优化、语义不一致等实际问题。用
pandas.json_normalize() 展平嵌套字典
API 返回的 JSON 数据通常包含多层嵌套(例如(例如) "user": {"profile": {"name": "Alice", "tags": ["dev", "python"]}}),直接传给 pd.DataFrame() 将整层作为字符串或 dict 存入单元格。必须先展平。
pandas.json_normalize() 它是专门为此设计的函数,可以递归提取嵌套字段,生成扁平列名(如 user.profile.name)。关键参数:
-
record_path:指定最深层次的“记录列表”路径(如["data", "items"]),提取多个同构数据 -
meta:声明需要提升到顶层的父级字段(如["id", "user.profile.name"]) -
sep:默认情况下,设置嵌套列名分隔符.,可改用_避免点号在后续操作中引起语法歧义
示例:若 API 返回 {"status": "ok", "data": [{"id": 1, "user": {"name": "Bob", "addr": {"city": "Shanghai"}}}]},执行 pandas.json_normalize(data, record_path=["data"], meta=["status"], sep="_") 得到三列:id、user_name、user_addr_city、status。
KeyError 或者缺失字段怎么办?
真实 API 在响应中,嵌套字段往往不完整——记录缺失 "user",另一条缺 "user.addr"。默认 json_normalize() 会报 KeyError 或填 None,但列结构可能会出现混乱。
立即学习“Python免费学习笔记(深入);
安全方法是预设字段路径并容错:
- 用
errors="ignore"参数跳过无法分析的路径(谨慎使用,可能掩盖结构问题) - 更可靠的是先统一补充缺失层次:使用原始响应列表
dict.setdefault()空字典逐层初始化,然后传入json_normalize() - 若字段类型混杂(如有时)
dict,有时是None),展平后该列 dtype 会变成object,后续用pd.Series.map()或.str.get()提取子字段时需要添加na_action="ignore"
"tags": ["a", "b"])
json_normalize() 默认情况下,将列表原样插入单元格,不会自动展开成多行。要想“爆炸”成行(即一对多展开),必须手动处理。
Python 3.14.2
Python 3.14.2是Python编程语言于2025年12月5日发布的稳定版本,属于3.14系列的第二次维护更新。该版本包含18个修复项目,重点解决多过程、数据和正则表达模块的回归问题,修复CVE-2025-12084等安全漏洞。这个版本标志着Python发展的一个重要里程碑,即自由线程模式(删除GIL)正式得到官方支持。
下载典型流程:
- 先用
json_normalize()得到含列表的 DataFrame - 对于目标列(如
tags)调用explode()方法:df.explode("tags"),每个项目单独一行 - 如果列表项本身是字典(例如)
[{"id": 1}, {"id": 2}]),再对新列用json_normalize()单独展平,或使用pd.json_normalize(df["tags"].dropna())提取后merge回主表
注意:explode() 其他列值将被复制。如果原始数据量大,列表长,内存占用激增-首先确认是否真的需要扩展或使用 str.join() 或 apply(list) 更适合保留聚合形式。
json_normalize()
有些人习惯于对待每一个 API 分页响应是单独的 json_normalize() 再 pd.concat(),当响应结构一致时,这是可行的,但效率低下:每次分析都重建列映射 concat 多次触发内存副本。
正确的姿势是:
- 收集所有原始响应(列表) of dict),一次性传入
json_normalize() - 若各页结构微异(如某些页多一个字段),首先使用
pd.json_normalize([{})空跑一次获得完整的列集,然后使用reindex(columns=full_cols)对齐 - 极端情况(超深嵌套或动态) key),考虑用
jsonpath-ng关键路径提前提取,再结构干净 dict 列表喂给pd.DataFrame()
真正的麻烦不是嵌套深度,而是字段语义不稳定——比如 "metadata" 有时是字典,有时是字符串,有时是空的。这必须在那里 json_normalize() 通过参数无法解决之前的清洁问题。