当前位置: 首页 > 图灵资讯 > 行业资讯> Python Pandas如何处理API返回的深层嵌套字典数据?

Python Pandas如何处理API返回的深层嵌套字典数据?

来源:图灵python
时间: 2026-07-21 17:05:04
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="_") 得到三列:iduser_nameuser_addr_citystatus

遇到 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() 通过参数无法解决之前的清洁问题。