JSON keys shuffled in Python

I am parsing JSON from a web api, and Python seems to shuffle the keys when I iterate over them.

The original JSON in the screenshot (this is the correct original order. No, it is not only sorted alphabetically): Original json

My code is:

data = requests.get('http://www.dota2.com/jsfeed/heropediadata?feeds=abilitydata&l=english').json() for key in data['abilitydata']: print key 

And the conclusion:

 tiny_avalanche rubick_fade_bolt doom_bringer_devour undying_flesh_golem ... 

I also tried to do this via urllib and json.loads () - it gives the same result.

How can I reach the initial order?

+5
source share
4 answers

You can use the ordered dictionary and object_pairs_hook argument of load method in json package. Here is an example of working code:

 import json import requests from collections import OrderedDict result = requests.get('http://www.dota2.com/jsfeed/heropediadata?feeds=abilitydata&l=english') data = json.loads(result.text, object_pairs_hook = OrderedDict) 

the data will contain your dictionary keys in order

+5
source

As others have said, dict disordered. collections.OrderedDict is a subclass of dict whose keys are ordered. The problem is that json.load returns the dict directly, and we cannot just throw the result into the OrderedDict , since the order of the keys has already lost information at this point.

We need a way to tell json.load to return an OrderedDict instead of a dict . This can be done by implementing a custom json.JSONDecoder that supplies object_pairs_hook . object_pairs_hook receives the JSON object as a list of tuples (key, value) in the order they appear in the JSON document. It should return a translation of this object into a Python object. We will pass this list of tuples to the initializer for collections.OrderedDict , and this should do the trick.

Here is the code:

 data = """ { "foo": "bar", "a_list": [1, 2, 3], "another_object": { "c": 3, "a": 1, "b": 2 }, "last_key": 42 } """ decoder = json.JSONDecoder(object_pairs_hook=collections.OrderedDict) result = decoder.decode(data) print(result) 

which gives:

 OrderedDict([('foo', 'bar'), ('a_list', [1, 2, 3]), ('another_object', OrderedDict([('c', 3), ('a', 1), ('b', 2)])), ('last_key', 42)]) 

Finally, you might be wondering: "Why is there so much extra work?" Well, JSON should not be considered as a data structure with any fixed order. You go against the grain by doing this.

+3
source

Since Python dictionaries are unordered.

When you parse the JSON text, you get a dictionary. Since the dictionary type is not ordered, keys can only be repeated in undefined order.

+1
source

dict Type is a built-in type in Python. He is disordered.

If you want to restore the order of the keys in the dict, you can use the OrderedDict from the collections class.

See this example:

 >>> import collections >>> data = collections.OrderedDict() >>> data['pear'] = 1 >>> data['apple'] = 3 >>> data['orange'] = 2 >>> data['lemon'] = 4 >>> >>> >>> print data OrderedDict([('pear', 1), ('apple', 3), ('orange', 2), ('lemon', 4)]) >>> >>> >>> data2 = dict() >>> data2['pear'] = 1 >>> data2['apple'] = 3 >>> data2['orange'] = 2 >>> data2['lemon'] = 4 >>> >>> >>> print data2 {'orange': 2, 'lemon': 4, 'pear': 1, 'apple': 3} >>> 

For more information, go to: https://docs.python.org/2/library/collections.html#collections.OrderedDict

+1
source

All Articles