pandas.json_normalize()专用于展平多层嵌套json,需正确设置record_path指定展开列表路径、meta保留父级字段、errors="ignore"容错、sep="_"避免列名冲突,并对内层列表二次explode或json_normalize处理。

用 pandas.json_normalize() 处理多层嵌套字典
直接调用 pd.DataFrame() 会把嵌套字典整个塞进一个单元格,根本没法分析。必须用 pandas.json_normalize() —— 它专为扁平化 JSON/API 响应设计,比手写递归解析快且稳定。
关键不是“能不能”,而是“怎么选参数”。常见错误是只传 data,结果字段全挤在顶层,深层键名丢失或被覆盖。
-
record_path指定要展开的嵌套列表路径,比如["data", "items"];不填就默认展开最外层数组 -
meta列出你想保留的父级字段,支持嵌套路径写法,如["metadata", "request_id"] -
errors="ignore"防止某条记录缺某个嵌套字段时整个解析失败 - 如果嵌套结构不统一(有的有
user.profile,有的没有),加sep="_"避免列名冲突(默认是.)
当嵌套里还含列表:先定位再展开
API 返回中常见 "tags": ["a", "b"] 或 "comments": [{"id":1,"text":"..."}] 这类结构。json_normalize() 默认不展开内层列表,会原样存成 Python list 对象。
解决方法分两步:先用 record_path 提取目标列表,再对结果中仍含列表的列做二次处理。
- 对字符串数组(如
tags),用df.explode("tags")拆成多行 - 对字典数组(如
comments),先json_normalize()展开该列:pd.json_normalize(df["comments"].explode().dropna()) - 注意
explode()会复制父级字段,若只想保留关联 ID,提前提取df[["id"]].explode("comments")再合并
遇到 TypeError: unhashable type: 'dict' 怎么办
这通常发生在你试图用嵌套字典做 groupby、merge 或设为索引时。Pandas 不允许 dict 类型参与哈希操作。
- 检查列类型:
df["raw_data"].apply(type).unique()确认是不是混了 dict 和 None - 快速清洗:用
df["raw_data"].apply(lambda x: str(x) if isinstance(x, dict) else x)转字符串(适合调试) - 真正处理:先
json_normalize()扁平化,再删掉原始嵌套列,别留着“备用” - 如果必须保留原始结构,改用
df["raw_data"].apply(json.dumps)序列化为字符串
性能差?试试 max_level 和预过滤
大响应(>10k 条)下 json_normalize() 可能变慢,尤其嵌套深、字段多。不是函数本身慢,而是默认展开所有层级导致冗余列爆炸。
- 用
max_level=1限制只展开一层,再手动处理关键子字段 - 提前用
response.get("data", [])或[r for r in response["results"] if r.get("status") == "active"]过滤数据,别把整块 JSON 丢给json_normalize - 避免重复解析:把 API 响应存成
.json文件,调试时直接读文件,别反复调接口
嵌套越深,record_path 和 meta 的路径写错就越难排查——建议先用 print(json.dumps(data, indent=2)[:500]) 截取前几行看结构,再动手写路径。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











