当前位置:  开发笔记 > 编程语言 > 正文

Python的json模块,将int字典键转换为字符串

如何解决《Python的json模块,将int字典键转换为字符串》经验,为你挑选了5个好方法。

我发现当运行以下命令时,python的json模块(包含在2.6之后)将int字典键转换为字符串.

>>> import json
>>> releases = {1: "foo-v0.1"}
>>> json.dumps(releases)
'{"1": "foo-v0.1"}'

有没有简单的方法将密钥保存为int,而无需在转储和加载时解析字符串.我相信可以使用json模块提供的钩子,但是这仍然需要解析.可能有一个我忽略的争论吗?干杯,chaz

子问题:谢谢你的回答.看到j​​son像我担心的那样工作,是否有一种通过解析转储输出来传达密钥类型的简单方法?另外我应该注意执行转储的代码和从服务器下载json对象并加载它的代码都是由我编写的.



1> Jim Dennis..:

这是可以咬你的各种映射集合之间的微妙差异之一.

在Python中(显然在Lua中)映射的键(分别是字典或表)是对象引用.在Python中,它们必须是不可变类型,或者它们必须是实现__hash__方法的对象.(Lua文档建议它自动使用对象的ID作为哈希/键,即使对于可变对象,也依赖于字符串实习以确保等效字符串映射到相同的对象).

在Perl,Javascript,awk和许多其他语言中,哈希,关联数组或它们为给定语言调用的任何键都是字符串(或Perl中的"标量").在perl $foo{1}, $foo{1.0}, and $foo{"1"}中都是对相同映射的引用%foo---键被评估为标量!

JSON最初是一个Javascript序列化技术.(JSON代表[J] ava [S] cript [o] bject [n] otation.)当然,它为其映射表示法实现语义,这与其映射语义一致.

如果序列化的两端都是Python,那么你最好使用泡菜.如果你真的需要将这些从JSON转换回本机Python对象,我猜你有几个选择.首先,您可以尝试(try: ... except: ...)在字典查找失败的情况下将任何键转换为数字.或者,如果您将代码添加到另一端(此JSON数据的序列化程序或生成器),那么您可以让它对每个键值执行JSON序列化 - 将它们作为键列表提供.(然后你的Python代码首先遍历键列表,将它们实例化/反序列化为本机Python对象......然后使用它们来访问映射中的值).


使用Pickle的建议要谨慎.Pickle会导致任意代码执行,因此如果您要反序列化的数据源本身并不值得信任,那么您应该坚持使用像JSON这样的"安全"序列化协议.还要记住,随着项目范围的扩展,有时您期望的功能只能获得可信输入,开始获得用户提供的输入,并且不会始终重新考虑安全性考虑因素.

2> bobince..:

不,JavaScript中没有数字键这样的东西.所有对象属性都转换为String.

var a= {1: 'a'};
for (k in a)
    alert(typeof k); // 'string'

这可能会导致一些看似奇怪的行为:

a[999999999999999999999]= 'a'; // this even works on Array
alert(a[1000000000000000000000]); // 'a'
alert(a['999999999999999999999']); // fail
alert(a['1e+21']); // 'a'

JavaScript对象不是真正适当的映射,因为您在Python等语言中理解它,并且使用非String的键会导致奇怪.这就是为什么JSON总是明确地将键写为字符串,即使它看起来不必要.


@PiotrDobrogost JavaScript(像许多语言一样)无法存储任意大数字.`Number`类型是[IEEE 754 double](https://en.wikipedia.org/wiki/IEEE_floating_point)浮点值:你得到53位尾数,所以你可以存储最多2⁵³(9007199254740992)的整数准确性; 除此之外,整数将舍入到其他值(因此9007199254740993 === 9007199254740992).999999999999999999999轮到1000000000000000000000,默认的`toString`表示为'1e + 21`.

3> Ashish..:

或者,您也可以尝试将字典转换为[(k1,v1),(k2,v2)]格式列表,同时使用json对其进行编码,并在将其解码后将其转换回字典.

>>>> import json
>>>> json.dumps(releases.items())
    '[[1, "foo-v0.1"]]'
>>>> releases = {1: "foo-v0.1"}
>>>> releases == dict(json.loads(json.dumps(releases.items())))
     True
我相信这需要更多的工作,比如有一些标志来识别从json解码后要转换为字典的所有参数.



4> Murmel..:

回答你的问题:

它可以通过使用来完成 json.loads(jsonDict, object_hook=jsonKeys2int)

def jsonKeys2int(x):
    if isinstance(x, dict):
            return {int(k):v for k,v in x.items()}
    return x

此函数也适用于嵌套dicts并使用dict理解.

如果您也想要转换值,请使用:

def jsonKV2int(x):
    if isinstance(x, dict):
            return {int(k):(int(v) if isinstance(v, unicode) else v) for k,v in x.items()}
    return x

它测试值的实例并仅在它们是字符串对象时才转换它们(确切地说是unicode).

两个函数都假定键(和值)是整数.

谢谢:

如何在词典理解中使用if/else?

在字典中将字符串键转换为int



5> AFoglia..:

我被同样的问题困扰了.正如其他人所指出的那样,在JSON中,映射键必须是字符串.你可以做两件事之一.您可以使用不太严格的JSON库,如demjson,它允许整数字符串.如果没有其他程序(或其他语言中没有其他程序)会读它,那么你应该没问题.或者您可以使用不同的序列化语言.我不会建议泡菜.它难以阅读,并且不是为了安全而设计的.相反,我建议YAML,它(几乎)是JSON的超集,并且允许整数键.(至少是PyYAML.)

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有