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?
@juanpa.arrivillaga To avoid conversion, and have it directly loaded back as a dict with integer keys. Well, since JSON requires string keys, you'll either have to write your own decoder (which is straightforward with the json library) or just convert, or chose an alternative serialization format.
Python JSON 1 Import json Module. To work with JSON (string, or file containing JSON object), you can use Python's json module. ... 2 Parse JSON in Python. The json module makes it easy to parse JSON strings and files containing JSON object. ... 3 Python Convert to JSON string. ... 4 Writing JSON to a file. ... 5 Python pretty print JSON. ...
I have found that when the following is run, python's json module (included since 2.6) converts int dictionary keys to strings. Is there any easy way to preserve the key as an int, without needing to parse the string on dump and load.
Read JSON data from a file and convert it into dict using json.load() Using a json.load() method, we can read JSON data from text, JSON, or binary file. The json.load() method returns data in the form of a Python dictionary. Later we use this dictionary to access and manipulate data in our application or system. Now, let’s see the example.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With