JSON键在Python中进行了混乱

时间:2015-08-20 19:13:09

标签: python json python-requests

我正在从web api解析JSON,而Python似乎在重复迭代时将这些密钥洗牌。

屏幕截图上的原始JSON(它是正确的原始排序。不,它不是按字母顺序排序): Original JSON

我的代码:

data = requests.get('http://www.dota2.com/jsfeed/heropediadata?feeds=abilitydata&l=english').json()

for key in data['abilitydata']:
    print key

输出:

tiny_avalanche
rubick_fade_bolt
doom_bringer_devour
undying_flesh_golem
...

我也试过通过urllib& json.loads() - 它给出了相同的结果。

如何才能实现原始订购?

4 个答案:

答案 0 :(得分:5)

您可以在json包中使用有序字典和loads方法的object_pairs_hook参数。这是一个有效的代码示例:

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)

数据将按顺序包含您的字典键

答案 1 :(得分:3)

正如其他人所说,dict是无序的。 collections.OrderedDict是一个dict子类,其键是有序的。问题是json.load直接返回dict,我们不能只将结果抛出OrderedDict,因为此时键的顺序已经丢失了信息。< / p>

我们需要一种方式告诉json.load返回OrderedDict而不是dict。这可以通过实现提供{{1}的自定义json.JSONDecoder来完成}}。 object_pairs_hook被赋予一个JSON对象作为object_pairs_hook元组的列表,按照它们在JSON文档中出现的顺序。它应该返回此对象到Python对象的转换。我们将这个元组列表交给(key, value)的初始化器,这应该可以解决问题。

以下是一些代码:

collections.OrderedDict

给出:

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)

最后,你可能想知道:“为什么这么多额外的工作呢?”好吧,JSON并不意味着被视为具有任何固定顺序的数据结构。你这样做是违背金钱的。

答案 2 :(得分:1)

因为Python词典是无序的。

解析JSON文本时,会得到一个字典。因为字典类型没有顺序,所以只能以未定义的顺序迭代键。

答案 3 :(得分:1)

dict类型是Python中的内置类型。这是无序的。

如果您希望能够恢复字典中的键顺序,可以使用OrderedDict类中的collections

见这个例子:

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

有关详情,请参阅:https://docs.python.org/2/library/collections.html#collections.OrderedDict