直接用 json.loads() 后遍历易出错,因嵌套深、类型混杂(dict/list/none/自定义对象),硬写递归易漏 list 中 dict 或在 none 调用 .items() 报错;键名重复(如多处 "user")导致扁平后冲突;flatten_dict 库需配置 separator="_"、enumerate_types=(list,)、keep_empty_types=() 才适配真实数据;手写函数须支持 max_depth 和 skip_keys 过滤无用字段。

为什么直接用 json.loads() 后遍历会出错?
因为嵌套层级深、类型混杂(dict、list、None、甚至自定义对象),硬写递归容易漏掉 list 中的字典,或在 None 上调用 .items() 报 AttributeError。更麻烦的是键名重复——比如多个 {"user": {"id": 1}} 和 {"order": {"user": {"name": "A"}}},扁平后都可能生成 user_id,冲突不可避免。
flatten_dict 库能直接用,但要注意三个默认行为
第三方库 flatten_dict 确实省事,但它默认用 . 当分隔符、不处理 list、且把 None 变成空字符串。实际数据里常有数组字段(如 "tags": ["a", "b"])和缺失字段("phone": null),必须显式配置:
- 用
separator="_"避免点号在字段名中引发歧义(比如原始 key 是"v1.2.3") - 加
enumerate_types=(list,)才能把["x", "y"]展开成tags_0="x",tags_1="y" - 设
keep_empty_types=()防止None被转成"",保留为None更利于后续判断
手写扁平化函数时,max_depth 和 skip_keys 是刚需
真实业务 JSON 常含大段无用字段(如 "debug_info"、"raw_xml"),全展开既慢又占内存。手写时务必支持深度限制和键过滤:
def flatten_json(obj, prefix="", sep="_", max_depth=5, skip_keys=("debug_info", "meta")):
if max_depth <p>注意:这里 <code>skip_keys</code> 是元组而非列表,避免被误修改;<code>max_depth</code> 从外向内递减,到 0 就截断并打标记,比单纯抛异常更可控。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill4292" title="jm-jsjkxyjs02-pzl-803"><img
src="https://img.php.cn/upload/skill/000/000/081/178998482628832.jpg" alt="jm-jsjkxyjs02-pzl-803" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill4292" title="jm-jsjkxyjs02-pzl-803" class="overflowclass">jm-jsjkxyjs02-pzl-803</a>
<p class="overflowclass">查询全球任意城市的实时天气和未来天气预报</p>
</div>
<a rel="nofollow" href="/xiazai/skill4292" title="jm-jsjkxyjs02-pzl-803" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><h3>扁平后字段爆炸?用 <code>pandas.json_normalize</code> 做定向提取</h3><p>当只关心某几层(比如所有 <code>user.name</code> 和 <code>order.items[].price</code>),不用全量扁平。用 <code>pandas.json_normalize</code> 指定 <code>record_path</code> 和 <code>meta</code> 更高效:</p><pre class="brush:php;toolbar:false;">import pandas as pd
df = pd.json_normalize(
data,
record_path=["orders", "items"], # 提取嵌套数组
meta=[["user", "id"], ["user", "name"], ["order_id"]], # 提取父级字段
errors="ignore"
)关键点:errors="ignore" 防止某条记录缺 user 字段就整个失败;meta 中用列表表示嵌套路径,比手拼 key 安全;返回是 DataFrame,天然支持去重、筛选、导出,比纯字典更适合后续分析。
复杂嵌套里最易忽略的不是怎么展,而是“展到哪”——没约束的扁平化等于制造新混乱。字段命名冲突、list 处理方式、空值表示、性能边界,每个都得在动手前想清楚。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










