为啥在使用 json.dumps 时,python dict 的 int 键会变成字符串?
Posted
技术标签:
【中文标题】为啥在使用 json.dumps 时,python dict 的 int 键会变成字符串?【英文标题】: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
【参考方案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
【讨论】:
以上是关于为啥在使用 json.dumps 时,python dict 的 int 键会变成字符串?的主要内容,如果未能解决你的问题,请参考以下文章
python json.dumps()函数输出json格式,使用ensure_ascii参数对中文输入的支持
[转]python json.dumps 中的ensure_ascii 参数引起的中文编码
python json.dumps 中的ensure_ascii 参数引起的中文编码问题
python json.dumps 中的ensure_ascii 参数引起的中文编码问题