Python + JSON,None去哪了?
当你把一个字典(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}