最稳妥的嵌套json解析起点是json.loads(),但关键在于后续健壮取值、类型校验与契约保障:用safe_get函数安全取值,显式处理null/空值/字符串数字,慎用扁平化,优先采用jsonschema校验源头schema。

直接用 json.loads() 解析嵌套 JSON 是最稳妥的起点,但真正麻烦的是后续取值、容错和类型不一致问题——不是解析失败,而是取 data["user"]["profile"]["address"]["city"] 时突然报 KeyError 或 TypeError。
嵌套字典取值总抛 KeyError?用 get() 链式调用不现实
手动写 data.get("user", {}).get("profile", {}).get("address", {}).get("city") 看似安全,但路径一长就难维护,且无法区分“键不存在”和“值为 None”。更实际的做法是封装一个健壮的取值函数:
def safe_get(d, *keys, default=None):
for k in keys:
if isinstance(d, dict) and k in d:
d = d[k]
else:
return default
return d
<h1>使用示例</h1><p>city = safe_get(data, "user", "profile", "address", "city", default="Unknown")</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill4769" title="Python Testing"><img
src="https://img.php.cn/upload/skill/000/000/081/179021887894914.jpg" alt="Python Testing" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill4769" title="Python Testing" class="overflowclass">Python Testing</a>
<p class="overflowclass">Python 测试速查:运行 pytest、使用 mock/patch、参数化、fixtures、异步、覆盖率测试。</p>
</div>
<a rel="nofollow" href="/xiazai/skill4769" title="Python Testing" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 它比
dict.get()链更清晰,支持任意深度,且只在路径断裂时返回default - 注意:如果中间某层是
list(比如"orders": [{"id": 1}, {"id": 2}]),这个函数会直接返回default—— 这是设计使然,不是 bug - 若需支持 list 索引(如
["user", "orders", 0, "id"]),得额外判断isinstance(d, list)并处理整数 key
JSON 中混着字符串数字、null、空数组?类型校验不能省
API 返回的 JSON 经常不守规矩:"age": "25"、"tags": null、"phone": ""。硬转 int(data["age"]) 或遍历 data["tags"] 会立刻崩。
- 对关键字段做显式类型转换 + 容错:用
int(data.get("age") or 0)比int(data["age"])安全得多 -
null在 Python 是None,但None不能被len()、迭代或索引 —— 处理前先用if data.get("tags") is not None:判断 - 空字符串
""和空列表[]都是 falsy,但语义不同;需要区分时别只用if data.get("phone"):
想把嵌套结构扁平化?别手写递归,用现成工具或明确边界
把 {"user": {"name": "Alice", "contact": {"email": "a@b.c"}}} 变成 {"user.name": "Alice", "user.contact.email": "a@b.c"} 听起来方便,但实际容易踩坑:
- 字段名含点号(如
{"v1.2": {"ok": true}})会导致歧义 —— 扁平化后"v1.2.ok"看不出原结构 - 同名键在不同层级(如
{"id": 1, "data": {"id": 2}})扁平后冲突,必须加前缀或放弃 - 推荐做法:只对已知稳定结构做有限扁平,例如用
jsonpath-ng库精准提取路径:parse("$.user.profile.city").find(data),比自己遍历更可靠
最常被忽略的其实是数据源头的契约意识:没有 schema 的嵌套 JSON 就像没有注释的函数,再好的解析逻辑也扛不住字段突然消失或类型突变。上线前至少用 jsonschema 做一次校验,比事后修 bug 成本低得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










