Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read a JSON and convert the keys to int

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?

like image 318
Basj Avatar asked Oct 29 '18 17:10

Basj


People also ask

How to avoid conversion from JSON to integer?

@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.

How do I convert JSON to Python?

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. ...

Can Python's JSON Module Convert int dictionary keys to strings?

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.

How to read JSON data from a file and convert to Dict?

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.


Video Answer


2 Answers

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 of object_hook will be used instead of the dict.


Or, you could also use 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 of object_pairs_hook will be used instead of the dict.

like image 146
Austin Avatar answered Sep 20 '22 00:09

Austin


I also want to add another solution if you would have a nested dictionary.


I've seen this solution under another question which handles ordinary dictionaries and also nested dictionaries which gives error if you have non-integer keys in the second layers.
>>> 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.

like image 43
Isa Kilikya Avatar answered Sep 22 '22 00:09

Isa Kilikya