Python 解析 JSON:重复字段为什么只剩最后一个?

举报
yd_239549656 发表于 2026/11/08 09:42:12 2026/11/08
【摘要】 用三段可运行示例复现 json.loads 的同名字段覆盖,比较键值对保留与拒绝重复字段,并验证嵌套对象、转义字段名及不同对象的同名键等边界。

导入一段 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-object
  • docs.python.org/3/library/json.html#json.load

AI 辅助说明:本文由 AI 协助组织文字与编写示例,示例已实际执行,相关行为已结合官方文档与独立断言核对。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。