44

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

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

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

当我使用 json 模块将其序列化为 JSON 字符串时,值被写为数字,但键被写为字符串:

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

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

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

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

4

3 回答 3

49

原因很简单,JSON 不允许整数键。

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

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

于 2013-06-14T00:58:18.667 回答
1

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

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
于 2018-09-20T11:54:27.493 回答
1

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

我稍微调整了下面JLT 的示例。对于我的一些巨大的嵌套字典,代码使字典的大小发生了变化,并以异常结束。无论如何,功劳归于 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
于 2019-04-25T05:53:19.303 回答