Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JSON键在Python中被洗牌_Python_Json_Python Requests - Fatal编程技术网

JSON键在Python中被洗牌

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

我正在解析来自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_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)。谢谢!很好的解释。谢谢,这对我很有用&这是最短的解决方案:)