【问题标题】:Python json module generates non-unique keysPython json 模块生成非唯一键
【发布时间】:2018-07-06 19:05:37
【问题描述】:

根据 JSON 规范 https://www.rfc-editor.org/rfc/rfc8259 对象的键应该是唯一的

  1. 对象

对象结构表示为一对花括号
围绕零个或多个名称/值对(或成员)。名字就是一个
细绳。每个名称后面都有一个冒号,用于分隔名称
从价值。单个逗号将值与以下值分开
姓名。 对象中的名称应该是唯一的

但是可以使用两个相同的键创建 json 对象

Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
>>> import json
>>> json.dumps({1: 'value1', "1": 'value2'})
'{"1": "value1", "1": "value2"}'

这是一个错误吗?

【问题讨论】:

  • 不,你有责任传递一个字典,其中的键将呈现不同的输出。
  • 您给定的数据具有唯一键。一个是整数1,另一个是包含"1"的长度为1的字符串。 btw json 在对象中只能有字符串键。
  • @quamrana,是的,我的 dict 有不同的键,我知道,我说的是生成的 json 对象
  • 因此,如果您要创建一个与json 兼容的dict,那么json.dumps() 将产生有效的json。如果您将该输出字符串传递给json.loads(),会发生什么?
  • 请注意,json.load 提供了一个 object_pairs_hook 关键字参数,您可以使用该参数正确加载具有重复键的对象而不会丢失数据。

标签: python json


【解决方案1】:

JSON spec 中,对象(如字典)是:

对象结构表示为一对花括号 围绕零个或多个名称/值对(或成员)。 名字是一个 字符串。

强调我的。 Python 的json.dumps 对输入对象非常宽容。它将隐式地将整数键转换为字符串,这可能会导致数据丢失/键冲突,就像您在此处看到的那样。它还打破了往返loads(dumps(d))

如果在您的上下文中担心数据丢失,请考虑使用更严格的 json 库,例如

>>> import demjson  # pip install demjson
>>> demjson.encode({1: 'value1', "1": 'value2'}, strict=True)
# JSONEncodeError: ('object properties (dictionary keys) must be strings in strict JSON', 1)

是不是出错了?

在我看来,是的。我已经看到了很多由此引起的错误,如果 stdlib json.dumps 默认情况下是严格的,并且使用 opt-in 关键字参数来启用任何隐式转换,我会更喜欢。但是,在 Python 中这种情况发生变化的可能性几乎为零。

【讨论】:

    【解决方案2】:

    JSON RFC 说“密钥应该是唯一的”。 RFC 对“应该”有非常具体的含义。来自https://www.rfc-editor.org/rfc/rfc2119

    应该:这个词,或形容词“推荐”,意味着有 在特定情况下可能存在忽略 特定项目,但必须了解全部含义并 在选择不同的课程之前仔细权衡。

    所以 JSON 不被禁止有重复的键,虽然这是不可取的,我建议不要这样做。

    如果你想检查你的 dict 是否良好,你可以使用这个测试:

    def keys_are_unique(d):
        return len(d) == len(set(str(k) for k in d))
    

    【讨论】:

    • 替代测试:d == json.loads(json.dumps(d))
    • OP 问题中的字典{1: 'value1', "1": 'value2'} 将被您的keys_are_unique() 函数视为有效。
    猜你喜欢
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2014-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多