应使用 get_nested 替代链式索引避免 keyerror,支持任意深度与默认值;用 match 语句解析固定结构 json 更清晰安全;去重嵌套字典需转元组或序列化;json_normalize 前先用 get_nested 提取 record_path。

用 get_nested 替代链式索引,避免 KeyError
直接写 data["a"]["b"]["c"] 是最常见也最容易翻车的写法。只要中间任意一层缺失(比如 "b" 不存在),立刻抛出 KeyError,而且错误堆栈很难快速定位是哪一层挂了。
更稳妥的做法是用嵌套 get() 或封装一个通用函数:
-
data.get("a", {}).get("b", {}).get("c")—— 简单场景够用,但层级一多就冗长 - 用
functools.reduce写个get_nested(data, ["a","b","c"], default="N/A"),支持任意深度、任意默认值 - 注意:如果某层值是
None,而你又没传default,那下一层.get()会报AttributeError(NoneType没有get方法),所以中间必须兜底成空字典{}
Python 3.10 的 match 语句适合解析结构化响应
当你拿到的是 HTTP API 返回的 JSON,且结构相对固定(比如总是有 {"status": "ok", "data": {...}} 或 {"error": "xxx"}),match 比一堆 if "data" in resp and "items" in resp["data"]: 清晰得多。
示例:
match response:
case {"status": "ok", "data": {"items": list(items)}}:
process_items(items)
case {"error": str(msg)}:
log_error(msg)
case _:
raise ValueError("unexpected response format")
- 它天然支持解构:
{"data": {"items": list(items)}}既校验键存在,又把items绑定为变量 - 不匹配时不会静默失败,
case _能兜底并给出明确提示 - 注意:模式中写
list(items)要求该字段确实是list类型;若可能是None或其他类型,得先做类型检查或改用更宽松的模式
去重嵌套字典列表,别用 set(raw_list)
TypeError: unhashable type: 'dict' 这个报错几乎人人都踩过。根本原因是字典可变、不可哈希,不能放进 set。
真正能用的方案取决于你的数据特征:
- 如果字典结构简单、字段少,且你只关心内容一致(不关心键顺序):
unique = [dict(t) for t in {tuple(d.items()) for d in raw_list}]—— 把每个字典转成元组再进集合,最后还原 - 如果字段多、含嵌套或有
None/list值,items()会失败,此时用json.dumps(d, sort_keys=True)生成唯一字符串再去重更稳 - 如果数据量极大(>10 万条),上述方法内存开销大,建议先按关键字段(如
"id")用dict去重:{d["id"]: d for d in raw_list}.values()
用 json_normalize 扁平化前,先确认 record_path 是否真存在
pandas.json_normalize 是处理嵌套 JSON 转 DataFrame 的利器,但它的 record_path 参数非常“刚”:如果路径不存在(比如 "items" 键压根没出现),默认抛 KeyError,而不是返回空 DataFrame。
实战建议:
- 加
errors="ignore"让它跳过缺失路径,但注意这会导致整行丢失,不是你想看到的“空值填充” - 更可控的做法是先用
get_nested提取record_path对应的数据,再传给json_normalize—— 至少你知道输入是什么 - 如果嵌套里有
datetime字符串,json_normalize默认当普通字符串处理;想自动转类型,得配合convert_dates参数或后续用pd.to_datetime()
嵌套结构的健壮性不来自“写得短”,而来自对每一层类型和存在性的显式判断。哪怕多写两行 .get() 或一个 match 分支,也比靠运气跑通强。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











