Python + JSON,None发生了什么?

35

当使用 None 作为字典的键进行序列化和反序列化时,会导致生成一个以字符串 'null' 作为键的 字典

值不受影响,但如果实际存在一个字符串键 'null',情况会变得更糟。

我在这里做错了什么?为什么无法对具有 None 键的 dict 进行序列化/反序列化操作?

示例

>>> json.loads(json.dumps({'123':None, None:'What happened to None?'}))
{u'123': None, u'null': u'What happened to None?'}
>>> json.loads(json.dumps({'123':None, None:'What happened to None?', 'null': 'boom'}))
{u'123': None, u'null': u'boom'}

3
顺便提一下,第二段代码的输出似乎已经被篡改了。 - Bleeding Fingers
3个回答

49

JSON对象是从 字符串 映射到值的。如果您尝试使用其他类型的键,它们将被转换为字符串。

>>> json.loads(json.dumps({123: None}))
{'123': None}
>>> json.loads(json.dumps({None: None}))
{'null': None}

22

根据规范None不是一个有效的键。它将转换为一个JSON对象表达式,看起来像:

{ ..., null: ..., ... }

该值无效(即不能使用语法图生成)。

可以说,JSON 模块在序列化时应该引发异常,而不是默默地生成值的字符串表示。

编辑 刚刚看到,该模块的行为已经记录在案(有些含蓄):

如果 skipkeys 为 True(默认为 False),则不属于基本类型(str、unicode、int、long、float、bool、None)的字典键将被跳过,而不是引发 TypeError。

因此,这种行为似乎是有意为之的(尽管我仍然认为它与当前的 JSON 规范不符)。


2
skipKeys对观察到的行为没有影响。 "None"是一种基本类型,因此skipKeys=True不会导致“跳过”,就像skipKeys=False不会导致TypeError一样。我希望在文档中有一个小注释,类似于:“对于可逆编码,只使用字符串作为键。” - safl

4

正如@dan04所示,None被转换为'null'

一切都很好,该值存储在字典中

"null": "What happened to None?"

但是,另一个被称为'null'的键出现了。

因此,None/'null'键的旧值("What happened to None?")被"boom"覆盖了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接