Reputation: 46473
It is well known that json
converts integer keys of a dict to string:
import json
print json.dumps({1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]})
# {"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}
What's the cleanest way to restore integer keys when loading it back?
d = json.loads('{"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}')
print d
# {u'1': [2.5, 2.5, 2.5], u'2': [3, 3, 3, 3]}
I was thinking about:
d = {int(k): d[k] for k in d}
but is there a cleaner way to deal with dictionaries with integer keys with JSON / Python, not requiring keys conversion a posteriori?
Upvotes: 10
Views: 9087
Reputation: 563
I also want to add another solution if you would have a nested dictionary.
>>> import json
>>> json_data = '{"1": "one", "2": {"-3": "minus three", "4": "four"}}'
>>> py_dict = json.loads(json_data, object_hook=lambda d: {int(k)
if k.lstrip('-').isdigit() else k: v for k, v in d.items()})
>>> py_dict
{1: 'one', 2: {-3: 'minus three', 4: 'four'}}
As we can see that object_hook is used to solve the problem, and lstrip('-') is used to handle negative values, too.
Upvotes: 5
Reputation: 26039
Use object_hook
to define a custom function and perform operations:
import json
def keystoint(x):
return {int(k): v for k, v in x.items()}
j = json.dumps({1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]})
# {"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}
print(json.loads(j, object_hook=keystoint))
# {1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]}
From docs:
object_hook
is an optional function that will be called with the result of any object literal decoded (a dict). The return value ofobject_hook
will be used instead of the dict.
object_pairs_hook
that lets you iterate through pairs and saves the .items()
call (Thanks @chepner):
import json
def keystoint(x):
return {int(k): v for k, v in x}
j = json.dumps({1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]})
# {"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}
print(json.loads(j, object_pairs_hook=keystoint))
# {1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]}
From docs:
object_pairs_hook
is an optional function that will be called with the result of any object literal decoded with an ordered list of pairs. The return value ofobject_pairs_hook
will be used instead of the dict.
Upvotes: 18