JSON键在Python中被洗牌
我正在解析来自web api的JSON,当我迭代时,Python似乎在洗牌键 屏幕截图上的原始JSON(正确的原始顺序。不,它不仅仅按字母顺序排序): 我的代码:JSON键在Python中被洗牌,python,json,python-requests,Python,Json,Python Requests,我正在解析来自web api的JSON,当我迭代时,Python似乎在洗牌键 屏幕截图上的原始JSON(正确的原始顺序。不,它不仅仅按字母顺序排序): 我的代码: data = requests.get('http://www.dota2.com/jsfeed/heropediadata?feeds=abilitydata&l=english').json() for key in data['abilitydata']: print key 和输出: tiny_avala
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()实现这一点-它给出了相同的结果
如何实现原始排序?因为Python字典是无序的
解析JSON文本时,会得到一个字典。因为字典类型没有顺序,所以只能以未定义的顺序迭代键。
dict
类型是Python中的内置类型。它是无序的
如果希望能够恢复dict中键的顺序,可以使用集合
类中的OrderedDict
请参见此示例:
>>> 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}
>>>
要了解更多信息,请浏览以下内容:正如其他人所说,
dict
是无序的collections.OrderedDict
是一个dict子类,其键是有序的。问题是,json.load
直接返回一个dict
,我们不能将结果抛出一个orderedict
,因为此时键的顺序已经丢失了信息
我们需要一种方法告诉json.load
返回一个OrderedDict
而不是dict
。这可以通过实现一个定制的json.JSONDecoder
来实现,它提供一个对象对\u钩子
。object\u pairs\u hook
以(key,value)
元组列表的形式提供一个JSON对象,这些元组按它们在JSON文档中出现的顺序排列。它应该返回这个对象到Python对象的转换。我们将把这个元组列表交给collections.orderedict
的初始值设定项,这样就可以了
下面是一些代码:
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)
其中:
OrderedDict([('foo', 'bar'),
('a_list', [1, 2, 3]),
('another_object', OrderedDict([('c', 3), ('a', 1), ('b', 2)])),
('last_key', 42)])
最后,你可能会想:“为什么这么多额外的工作?”。好吧,JSON并不意味着被视为具有任何固定顺序的数据结构。这样做是违反规则的。您可以在json包中使用有序字典和loads方法的object\u pairs\u 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)
数据将按顺序包含您的字典键谢谢您的解释。有没有一种方法可以使用原始顺序对其进行迭代?即使在使用维护顺序的Python类型(即OrderEdit,它必须通过和通过使用)时,在JSON中依赖这种行为仍然是不正确的;JSON本身并没有显式地建立键/值的顺序。@user2864740这只是实用程序解析器,而不是与产品相关的代码:)为什么您认为它需要有序?字典以及其他语言中的松散等价物通常被定义为键、值对的无序集合。JSON为此提供了
Object
。JSON文本中键的顺序是一种错觉,因为文本是序列化的。如果您解析它,然后再次序列化它,就不能保证键的顺序是相同的。您可以按对象读取它,并且在读取每个对象时添加一个顺序键。我从未使用过JSON,但我会想象这样的情况:首先读取文件,然后迭代每个对象,并在将其转换为JSON时添加一个新属性-原始orderA JSON对象是“一组无序的名称/值对”。如果最初指定键值对的顺序很重要,那么您真的不应该使用JSON对象(或者甚至不应该使用JSON)。谢谢!很好的解释。谢谢,这对我很有用&这是最短的解决方案:)