pandas.json_normalize() 更适合非结构化json,因其能递归展开嵌套、自动填充缺失键、支持record_path/meta处理数组字段,并通过errors和max_level参数应对不规则结构,而pd.dataframe()会将子对象存为list/dict导致后续操作失败。

直接用 pandas.json_normalize(),别先转 pd.DataFrame() 再处理——否则嵌套字段会变成 list 或 dict 对象,后续 explode 或 apply 会卡住或出错。
为什么 json_normalize() 比 pd.DataFrame() 更适合非结构化 JSON
原始 JSON 如果含多层嵌套(比如 "user": {"id": 1, "profile": {"name": "Alice"}}})、可变字段(某些记录有 "tags",某些没有)、或数组字段("comments": [{"text": "good"}, {"text": "ok"}]),pd.DataFrame() 会把整个子对象塞进一个单元格;而 json_normalize() 默认递归展开,自动处理缺失键(填 NaN),还能控制层级深度。
常见错误现象:ValueError: arrays must all be same length 或列里出现 [{'text': '...'}] 字符串/列表,说明没走 normalize 路径。
- 用
pd.json_normalize(data)处理顶层是 list 的 JSON(如 API 返回的 records 列表) - 若顶层是 dict(如
{"result": [...]}),先取data["result"]再传入 - 遇到重复字段名(如多层都有
"id"),默认用.连接路径,可通过sep="_"改为下划线
如何展开带数组字段(如 comments、tags)的 JSON
默认 json_normalize() 只展开 object 类型,对 list 类型字段(如 "comments": [...])保持原样——这正是“非结构化”最常卡住的地方。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
必须显式指定 record_path 和 meta:
-
record_path:指向要展开成行的数组字段,用字符串("comments")或路径列表(["user", "activity", "logs"]) -
meta:保留父级字段,支持字符串列表(["id", "timestamp"])或嵌套元组([("user", "name"), ("meta", "source")]) - 如果数组字段本身含嵌套对象,
json_normalize()会自动再展开一层,无需额外explode()
示例:pd.json_normalize(data, record_path="comments", meta=["post_id", ("user", "id")]) → 每条评论一行,附带所属 post_id 和 user.id
处理不规则结构(部分记录缺字段、字段类型不一致)
真实日志或爬虫数据经常出现同一 key 有时是 string、有时是 dict、有时干脆缺失。这时候 json_normalize() 的 errors 和 max_level 参数很关键:
-
errors="ignore":跳过无法解析的字段(比默认"raise"更鲁棒) -
max_level=1:限制展开深度,避免把深层嵌套全摊平导致列爆炸 - 若某字段在部分记录中是
null、部分是{}、部分是{"a": 1},建议先用pd.json_normalize()+errors="ignore",再对问题列用pd.json_normalize(df["broken_col"].dropna().tolist())单独处理 - 性能影响:
max_level设太低会留嵌套对象;设太高(尤其配合大数组)会显著拖慢,实测 >3 层且含数组时建议分步 normalize
真正麻烦的不是嵌套有多深,而是同一字段在不同样本中语义漂移——比如 "status" 有时是字符串 "active",有时是对象 {"code": 200, "msg": "OK"}。这种得先做 schema 探查,不能只靠 json_normalize() 一把梭。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










