
本文详解 Python 递归遍历 JSON 数据时因 if/else 逻辑错误(未使用 elif)导致子函数被意外多次执行的问题,并提供安全、简洁、可扩展的生成器式解决方案。
本文详解 python 递归遍历 json 数据时因 `if/else` 逻辑错误(未使用 `elif`)导致子函数被意外多次执行的问题,并提供安全、简洁、可扩展的生成器式解决方案。
在处理嵌套 JSON 结构(尤其是存在双重编码字符串,如 "textValue": "{\"text\":\"PAAT \"}")时,开发者常借助递归提取特定字段(如 "text")。但若控制流设计不当,极易引发同一对象被重复处理多次——表现为 print 输出重复、结果列表长度异常、甚至栈溢出。
? 根本原因:if + if + else 的逻辑陷阱
原代码中关键片段如下:
if key == "textValue":
# ... 解析并递归
if key == "text": # ← 这是独立的 if!
content.append(value)
return
else: # ← 当 key=="textValue" 为 True 时,此 else 仍可能执行!
process_data(value, content) # ❌ 错误:value 被二次递归
由于两个 if 是并列关系,当 key == "textValue" 成立时,第一个 if 块执行;紧接着第二个 if key == "text" 不成立,于是进入 else 分支——对 value 再次调用 process_data(),造成无意识的重复递归。正确做法是使用 elif 构建互斥分支:
SkillSub Pro - Python 题解与代码注释双功能技能功能概述SkillSub Pro - Python 题解与代码注释双功能技能是一项面向实际任务的技能,主要用于SkillSub Pro 是一个 Python 题解生成与代码注释的 双功能合体技能 ,专为学生、算法学习者和开发者设计;✅ 一个技能,两种用途 :;核心要点📝 题解模式 :输入题目/题号,自动生成完整 Python 题解(含详细注释、解题思路、复杂度分析);💬 注释模式 :输入 Python 代码,自动添加详细中。它将相关步骤、
if key == "textValue":
# 处理嵌套 JSON 字符串
nested = json.loads(value) # ✅ 只解码,不 encode 再 decode
yield from process_data(nested)
elif key == "text":
yield value # ✅ 直接产出目标值
else:
yield from process_data(value) # ✅ 其他键正常递归
✅ 推荐方案:使用生成器(yield / yield from)
相比传入可变列表参数(易出错、状态耦合),生成器更符合函数式思维,代码清晰且线程安全:
import json
def process_data(obj):
"""递归提取所有 'text' 字段值,自动处理 'textValue' 中的嵌套 JSON 字符串"""
if isinstance(obj, dict):
for key, value in obj.items():
if key == "textValue":
# 假设 textValue 的值是 JSON 字符串,需解析后继续递归
try:
nested_obj = json.loads(value)
yield from process_data(nested_obj)
except (json.JSONDecodeError, TypeError):
continue # 忽略无效 JSON
elif key == "text":
yield value
else:
yield from process_data(value) # 普通字段递归
elif isinstance(obj, list):
for item in obj:
yield from process_data(item)
? 完整可运行示例
if __name__ == '__main__':
# 使用 raw string 避免转义干扰
json_str = r'''{"textValue": "{\"type\":null,\"content\":[{\"content\":[{\"type\":\"text\",\"text\":\"PAAT \"}]}]}"}'''
# 仅用标准 json.loads 解析外层
data = json.loads(json_str)
# 提取所有 text 值
result = list(process_data(data))
print(result) # 输出: ['PAAT ']
⚠️ 注意事项与最佳实践
-
绝不手动字符串替换 JSON:如
replace('"{', '{')等操作极易破坏结构,应依赖json.loads()处理嵌套编码; -
避免冗余序列化:
json.dumps(value)后立刻json.loads(...)是无意义的 CPU 浪费; -
异常防御:对
json.loads()加try/except,防止非法嵌套字符串中断整个遍历; -
性能提示:对于超大 JSON,可考虑
ijson库实现流式解析,避免内存全载。
通过修正控制流逻辑 + 采用生成器模式,不仅能彻底解决“递归调用两次”的问题,还能让代码更健壮、可读、易维护。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










