>>> import json
>>> example = { 1: "banana", 2: "apple"}
>>> example
{1: 'banana', 2: 'apple'}
>>> json_example = json.dumps(example)
>>> json_example
'{"1": "banana", "2": "apple"}'
>>> from_str=json.loads(json_example)
>>> from_str
{'1': 'banana', '2': 'apple'}
My problem is quite simple, but I can't find a straightforward solution...
From a json encoded string (here json_example
), where keys represent numeric values, but are double quoted (because JSON standard allows only double quoted string as property key), I want to load a dict where keys are numeric values.
But json.loads
returns a dict where keys are strings. How can I get the keys as numeric values?
EDIT:
A one-liner like the one proposed by @not_speshal would be perfectly ok in most cases. But the context of this problem is a Django form (to read a json string provided by the user). I am looking for a solution which could involve a JSON decoder. So I can pass it as an argument to the Django forms.JSONField
class, to avoid subclassing this class and writing a lot of Django-specific code.
The most straightforward way I can think of is to go over the loaded dict and parse the str
keys into int
s like @not_speshal suggests in their comment .
{int(k): from_str[k] for k in from_str}
You could use the object_hook
argument to json.loads()
if you wanted a single function call to do the trick. This doesn't save any computations because the object is still read as a dict
with str
keys that you then convert to int
.
From the docs :
object_hook
is an optional function that will be called with the result of any object literal decoded (adict
). The return value ofobject_hook
will be used instead of thedict
. This feature can be used to implement custom decoders (eg JSON-RPC class hinting).
example = { 1: "banana", 2: "apple"}
json_example = json.dumps(example)
def parse_int_keys(dct):
rval = dict()
for key, val in dct.items():
try:
# Convert the key to an integer
int_key = int(key)
# Assign value to the integer key in the new dict
rval[int_key] = val
except ValueError:
# Couldn't convert key to an integer; Use original key
rval[key] = val
return rval
from_str = json.loads(json_example, object_hook=parse_int_keys)
# from_str is now
# {1: 'banana', 2: 'apple'}
The advantage of this approach is that it also works on nested dicts without having to write any more code:
obj = {'a': 1, 'b': {1: 'abc'}, 0: [1, 2, 3], '1234': 'Hi!'}
json.loads(json.dumps(obj), object_hook=parse_int_keys)
# Output:
# {'a': 1, 'b': {1: 'abc'}, 0: [1, 2, 3], 1234: 'Hi!'}
However, note that keys that were originally strings that can be parsed into integers (such as '1234'
in my example above) will still be converted to integers because we have no way of distinguishing between the two cases.
The simplest solution would be to create an empty dict and fill it while iterating through the first one and cast the keys to int values?
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.