Python + JSON, what happened to None?
Question:
Dumping and loading a dict with None
as key, results in a dictionary with 'null'
as the key.
Values are un-affected, but things get even worse if a string-key 'null'
actually exists.
What am I doing wrong here? Why can’t I serialize/deserialize a dict
with None
keys?
Example
>>> 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'}
Answers:
According to the specification, None
is not a valid key. It would amount to a JSON object expression, which looks like
{ ..., null: ..., ... }
which is not valid (i.e., cannot be generated using the syntax diagram.)
Arguably, the JSON module should have raised an exception upon serialization instead of silently generating a string representation of the value.
EDIT Just saw, that the behaviour of the module is documented (somewhat implicitly):
If skipkeys is True (default: False), then dict keys that are not of a basic type (str, unicode, int, long, float, bool, None) will be skipped instead of raising a TypeError.
so it seems, as if this behaviour is intentional (I still find it questionable given the current JSON specification).
JSON objects are maps of strings to values. If you try to use another type of key, they’ll get converted to strings.
>>> json.loads(json.dumps({123: None}))
{'123': None}
>>> json.loads(json.dumps({None: None}))
{'null': None}
As @dan04 shows, None
is converted to 'null'
.
Everything is fine, the value is stored into the dict with
"null": "What happened to None?"
But then came another Key called 'null'
.
So the old value of the None/'null'
-Key ("What happened to None?"
) is overwritten with "boom"
.
Dumping and loading a dict with None
as key, results in a dictionary with 'null'
as the key.
Values are un-affected, but things get even worse if a string-key 'null'
actually exists.
What am I doing wrong here? Why can’t I serialize/deserialize a dict
with None
keys?
Example
>>> 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'}
According to the specification, None
is not a valid key. It would amount to a JSON object expression, which looks like
{ ..., null: ..., ... }
which is not valid (i.e., cannot be generated using the syntax diagram.)
Arguably, the JSON module should have raised an exception upon serialization instead of silently generating a string representation of the value.
EDIT Just saw, that the behaviour of the module is documented (somewhat implicitly):
If skipkeys is True (default: False), then dict keys that are not of a basic type (str, unicode, int, long, float, bool, None) will be skipped instead of raising a TypeError.
so it seems, as if this behaviour is intentional (I still find it questionable given the current JSON specification).
JSON objects are maps of strings to values. If you try to use another type of key, they’ll get converted to strings.
>>> json.loads(json.dumps({123: None}))
{'123': None}
>>> json.loads(json.dumps({None: None}))
{'null': None}
As @dan04 shows, None
is converted to 'null'
.
Everything is fine, the value is stored into the dict with
"null": "What happened to None?"
But then came another Key called 'null'
.
So the old value of the None/'null'
-Key ("What happened to None?"
) is overwritten with "boom"
.