pandas.json_normalize专为处理不规则嵌套设计,可自动展开任意深度、补none、支持自定义分隔符和元数据;避免逐条调用、硬截断或手动递归,优先展开后统计。

用 pandas.json_normalize 处理不规则嵌套结构
直接用 pd.DataFrame() 读多层嵌套的字典列表,大概率报 ValueError: arrays must all be same length 或字段错位。根本原因是键路径深度不一致、部分路径缺失、列表长度不统一。
pandas.json_normalize 是专为此类场景设计的——它能自动展开任意深度的嵌套,把缺失路径补为 None,并支持自定义分隔符和元数据列。
- 对含
"user": {"id": 123, "profile": {"age": 28}}的列表,json_normalize(data, sep="_")生成列user_id和user_profile_age - 若某条记录缺
profile,对应行该列值为None,不会中断解析 - 遇到内嵌列表(如
"tags": ["a", "b"]),默认只取第一个元素;需传record_path显式指定展开路径,否则会丢数据 - 避免用
max_level截断过深结构——它按层级硬切,可能把本应同级的字段切到不同列名下
用 map + functools.reduce 安全取深层键值
当只需提取某几个固定路径(比如所有 data[i]["response"]["items"][0]["title"]),且嵌套中存在大量空值或键缺失时,手写递归 get() 容易出 KeyError 或 TypeError。更稳的方式是组合 map 和 reduce 做路径安全遍历。
- 定义函数
safe_get(d, *keys):用functools.reduce(lambda x, k: x.get(k) if isinstance(x, dict) else None, keys, d) - 对列表
data执行list(map(lambda x: safe_get(x, "response", "items", 0, "title"), data)),其中0是列表索引,也走get逻辑(需额外处理) - 注意:数字索引不能直接传给
dict.get(),所以safe_get内部要判断当前值是否为list并做索引检查,否则遇到"items": []会崩 - 比
try/except块批量包裹快,尤其在百万级数据上,异常开销明显
用 collections.Counter 统计嵌套字段频次前先展平
想统计所有 "category" 出现次数,但该字段藏在 item["meta"]["category"] 或 item["info"]["cat"] 甚至 item["tags"][0]["name"] 里?硬写三层循环 + 条件分支极易漏路径、难维护。
- 先用
json_normalize展开全部,再用df.filter(regex="category|cat|name").stack().dropna()提取所有疑似字段值 - 若字段命名太随意(如混用
type/kind/form),建议预定义映射字典{"type": "category", "kind": "category"},用df.rename(columns=...)归一化列名再统计 -
Counter本身不处理None或NaN,展平后务必加.dropna(),否则计数结果里会出现None: 12345 - 对超大列表,避免先转
DataFrame再stack()——内存翻倍。可改用生成器表达式:(v for row in data for v in extract_categories(row)),配合Counter流式计数
性能陷阱:别在循环里反复调用 json_normalize
有人为“保险”对每条记录单独调用 json_normalize 再拼 pd.concat,这会导致解析开销放大 N 倍,且列对齐失败风险极高。
-
json_normalize本质是单次扫描整个输入列表,内部已优化路径发现与缺失填充逻辑 - 若必须分批(如内存受限),用
itertools.islice切片原始列表,再整批送入json_normalize,而非逐条处理 - 确认输入是纯字典列表:含
datetime、numpy.ndarray等类型会触发TypeError: Object of type ... is not JSON serializable,需提前用json.dumps(..., default=str)预处理或替换为字符串 - 真正卡顿往往不在解析,而在后续
groupby或value_counts——确保关键统计字段已设为category类型,减少内存占用
嵌套越深,路径不确定性越高;与其纠结“怎么写对”,不如先用 json_normalize 看一眼实际展开后的列结构——多数统计需求,其实只需要两行代码:一行展开,一行 value_counts。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











