【问题标题】:Why do int keys of a python dict turn into strings when using json.dumps?为什么在使用 json.dumps 时,python dict 的 int 键会变成字符串?
【发布时间】:2013-06-10 13:49:03
【问题描述】:

根据this conversion table,当使用 JSON 模块进行序列化时,Python 整数会被写为 JSON 数字——正如我所期望和希望的那样。

我有一个带有整数键和整数值的字典:

>>> d = {1:2}
>>> type(d.items()[0][0])
<type 'int'>
>>> type(d.items()[0][1])
<type 'int'>

当我使用json模块将这个序列化为JSON字符串时,值写成数字,而key写成字符串:

>>> json.dumps(d)
'{"1": 2}'

这不是我想要的行为,而且它似乎特别糟糕,因为它打破了 json.dumps/json.loads 往返:

>>> d == json.loads(json.dumps(d))
False

为什么会发生这种情况,有没有办法可以强制将密钥写为数字?

【问题讨论】:

  • JSON 键是 always 字符串。
  • ...而 JSON 使用字符串,因为它们与字节顺序无关。
  • 如果 JSON 不是 严格 必需的,您可以使用 PyYAML 来代替 YAML:d = {1:2, 3:4}; import yaml; yaml.safe_load(yaml.safe_dump(d)) == d 返回 True。一般来说,YAML 的“内联”样式看起来像更灵活的 json(键可以是数字,通常不必引用字符串)。我在这里使用safe_load,因为普通yaml.load 具有难以正确保护的特性(类的构造等); safe_load|dump 将支持的输入/输出集限制为原始类型(bool、int、float、string、list、set、dict),因此可以安全地用于任意输入。
  • 不幸的是,往返行程不适用于 yaml.safe_dump,因为它将看起来像整数的字符串转换为整数。例如。试试 d = {'1':'2'}
  • 上述往返问题的错误:bitbucket.org/xi/pyyaml/issue/21

标签: python json serialization


【解决方案1】:

原因很简单,JSON does not allow integer keys.

object
    {}
    { members } 
members
    pair
    pair , members
pair
    string : value  # Keys *must* be strings.

关于如何绕过这个限制 - 您首先需要确保接收实现可以处理技术上无效的 JSON。然后,您可以替换所有引号或使用自定义序列化程序。

【讨论】:

  • 与普通的 javascript 不同。所有的键都应该被引用。
【解决方案2】:

如果你真的想要,你可以使用以下方法再次检查键是否可转换为整数:

def pythonify(json_data):
    for key, value in json_data.iteritems():
        if isinstance(value, list):
            value = [ pythonify(item) if isinstance(item, dict) else item for item in value ]
        elif isinstance(value, dict):
            value = pythonify(value)
        try:
            newkey = int(key)
            del json_data[key]
            key = newkey
        except TypeError:
            pass
        json_data[key] = value
    return json_data

【讨论】:

    【解决方案3】:

    如果可能,此函数将递归地将所有字符串键转换为整数键。如果不可能,键类型将保持不变。

    我稍微调整了下面的JLT's 示例。对于我的一些巨大的嵌套字典,代码使字典的大小发生了变化,并以异常结束。无论如何,功劳归于 JLT!

    def pythonify(json_data):
    
        correctedDict = {}
    
        for key, value in json_data.items():
            if isinstance(value, list):
                value = [pythonify(item) if isinstance(item, dict) else item for item in value]
            elif isinstance(value, dict):
                value = pythonify(value)
            try:
                key = int(key)
            except Exception as ex:
                pass
            correctedDict[key] = value
    
        return correctedDict
    

    【讨论】:

      猜你喜欢
      • 2021-09-13
      • 2016-02-29
      • 2014-01-18
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-01
      • 2018-04-14
      相关资源
      最近更新 更多