Python 解析 JSON:重复字段为什么只剩最后一个?
导入一段 JSON 配置时,如果同一个对象里写了两次 timeout,Python 的 json.loads 默认不会因为这个重复而报错。解析结果只留下后面的值,前面的设置很容易在检查时被忽略。
1. 先复现默认结果
import json
payload = '{"timeout": 5, "timeout": 30}'
parsed = json.loads(payload)
print(parsed) # {'timeout': 30}
这里两个字段的名字都是 timeout。默认解析成字典后,只能看到值 30。此时再检查 parsed 的键是否重复,已经无法还原原输入中出现过两次字段的事实。
如果业务约定每个对象内的字段名必须唯一,应在解析过程中保留或检查键值对,避免只依赖解析后的字典。
2. 先保留键值对,观察原来的顺序
import json
pairs = json.loads(
'{"timeout": 5, "timeout": 30}',
object_pairs_hook=list,
)
print(pairs) # [('timeout', 5), ('timeout', 30)]
object_pairs_hook 会接收 JSON 对象对应的有序键值对列表。这里直接传入 list,让两次出现的字段都保留下来,便于观察和诊断。
这样得到的对象表示是键值对列表,后续代码不能再直接把它当作原来的字典使用。嵌套 JSON 对象也会经过这个钩子,输出结构需要一起考虑。
3. 需要唯一字段时,明确拒绝重复
import json
def unique_object(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError("重复字段: " + key)
result[key] = value
return result
try:
json.loads(
'{"timeout": 5, "timeout": 30}',
object_pairs_hook=unique_object,
)
except ValueError as err:
print(err) # 重复字段: timeout
这个钩子在保存新字段前检查名字是否已经出现。即使两次字段的值相同,也会按“同一对象内字段名唯一”的约定拒绝。示例捕获异常只为展示结果;实际导入流程应把失败返回给调用方,由调用方决定如何修正输入。
不同对象各自包含 timeout 不属于同一对象内重复,例如 left 和 right 各有一个 timeout,就可以分别保留。检查也应基于解码后的字段名;转义写法不同,最终可能得到同一个名字。
实际验证与官方参考
上述三段示例已在本机独立运行,并验证了空对象、嵌套对象重复字段、不同对象的同名字段、相同值重复、转义字段名和 JSON 语法错误等边界。测试只处理文中的小字符串,没有读取真实配置文件。
Python 官方 json 文档中的 Repeated Names Within an Object 小节说明了默认的重复字段行为;Basic Usage 小节介绍了 object_pairs_hook。可按以下官方路径核对:
docs.python.org/3/library/json.html#repeated-names-within-an-objectdocs.python.org/3/library/json.html#json.load
AI 辅助说明:本文由 AI 协助组织文字与编写示例,示例已实际执行,相关行为已结合官方文档与独立断言核对。
- 点赞
- 收藏
- 关注作者
评论(0)