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

我发现,当以下运行时,python的json模块(包括自2.6以来)将int字典键转换为string。

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

有没有简单的方法来保存键为int,而无需parsing转储和加载string。 我相信这将有可能使用json模块提供的钩子,但是这仍然需要parsing。 有没有可能是我忽略的一个论点? 欢呼声,chaz

子问题:谢谢你的答案。 看到j​​son的工作,我担心,是否有一个简单的方法来传达键的types可能是parsing转储的输出? 另外我应该注意的代码做转储和代码从服务器上下载JSON对象,并加载它,都写我。

这是可以咬你的各种地图集合之间的细微差别之一。

在Python中(显然在Lua中),映射关键字(分别是字典或表)是对象引用。 在Python中,它们必须是不可变的types,或者它们必须是实现__hash__方法的对象。 (Lua文档build议,即使对于可变对象,它也会自动使用对象的ID作为散列/键,并依靠string内联来确保等价的string映射到相同的对象)。

在Perl,Javascript,awk和许多其他语言中,哈希值,关联数组或关于给定语言的任何键都是string(或Perl中的“标量”)。 在perl $foo{1}, $foo{1.0}, and $foo{"1"}都是对%foo相同映射的引用—键值被评估为标量!

JSON作为一个Javascript序列化技术开始。 (JSON代表[J] ava [S] cript [o] bject [n])。自然地,它的映射符号语义与其映射语义是一致的。

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

不,在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始终明确地将键写入string,即使它不是必要的。

或者,您也可以尝试将字典转换为[(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解码后,所有参数将被转换为字典。

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

回答你的问题:

它可以通过使用json.loads(jsonDict, object_hook=jsonKeys2str)

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

这个函数也适用于嵌套的字典,并使用字典理解。

如果你想要投入的价值,使用:

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

其中testing值的实例,只有在它们是string对象(精确到Unicode)时才会强制转换。

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

谢谢:

Python:if / else在词典理解?

在字典中将string键转换为int

你可以自己编写你的json.dumps ,下面是djson : encoder.py的一个例子。 你可以像这样使用它:

 assert dumps({1: "abc"}) == '{1: "abc"}'