Python + JSON,None去哪了?

36 投票
3 回答
120023 浏览
提问于 2025-04-16 03:10

当你把一个字典(dict)里用 None 作为键(key)进行存储和加载时,结果会变成一个字典,里面的键会变成 'null'

字典里的值(value)不会受到影响,但如果字典里本来就有一个字符串键 '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 个回答

5

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

一切都很好,这个值被存储到了字典里,使用的是

"null": "What happened to None?"

但是后来又出现了一个键叫 'null'

所以之前的 None/'null' 键的旧值("What happened to None?")被 "boom" 替换掉了。

22

根据规范None 不是一个有效的键。这会变成一个 JSON 对象表达式,像这样:

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

但是这是不合法的(也就是说,无法通过语法图生成)。

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

编辑 我刚看到,这个模块的行为在文档中有提到(虽然是有点隐晦):

如果 skipkeys 设置为 True(默认是 False),那么字典中不是基本类型(比如 str、unicode、int、long、float、bool、None)的键会被跳过,而不是抛出 TypeError。

所以看起来,这种行为是故意的(不过我觉得根据当前的 JSON 规范,这还是有点值得怀疑)。

49

JSON对象就像是一个把字符串和对应的值配对的地图。如果你试图用其他类型的键,比如数字,系统会把它们自动转换成字符串。

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

撰写回答