我正在使用json.dumps
转换为json,如
countries.append({"id":row.id,"name":row.name,"timezone":row.timezone})
print json.dumps(countries)
我的结果是:
[
{"timezone": 4, "id": 1, "name": "Mauritius"},
{"timezone": 2, "id": 2, "name": "France"},
{"timezone": 1, "id": 3, "name": "England"},
{"timezone": -4, "id": 4, "name": "USA"}
]
我想按以下顺序设置密钥:id,name,timezone - 但我有时区,id,名称。
我该如何解决这个问题?
答案 0 :(得分:195)
Python dict
(在Python 3.7之前)和JSON对象都是无序集合。您可以传递sort_keys
参数,对键进行排序:
>>> import json
>>> json.dumps({'a': 1, 'b': 2})
'{"b": 2, "a": 1}'
>>> json.dumps({'a': 1, 'b': 2}, sort_keys=True)
'{"a": 1, "b": 2}'
如果您需要特定订单;你可以use collections.OrderedDict
:
>>> from collections import OrderedDict
>>> json.dumps(OrderedDict([("a", 1), ("b", 2)]))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict([("b", 2), ("a", 1)]))
'{"b": 2, "a": 1}'
Since Python 3.6,保留关键字参数顺序,并且可以使用更好的语法重写上述内容:
>>> json.dumps(OrderedDict(a=1, b=2))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict(b=2, a=1))
'{"b": 2, "a": 1}'
请参阅PEP 468 – Preserving Keyword Argument Order。
如果您的输入是以JSON格式提供的,那么为了保留订单(获取OrderedDict
),您可以传递object_pair_hook
,as suggested by @Fred Yankowski:
>>> json.loads('{"a": 1, "b": 2}', object_pairs_hook=OrderedDict)
OrderedDict([('a', 1), ('b', 2)])
>>> json.loads('{"b": 2, "a": 1}', object_pairs_hook=OrderedDict)
OrderedDict([('b', 2), ('a', 1)])
答案 1 :(得分:19)
正如其他人所提到的,潜在的词典是无序的。但是在python中有OrderedDict对象。 (它们是在最近的蟒蛇中建造的,或者你可以使用它:http://code.activestate.com/recipes/576693/)。
我相信较新的pythons json实现正确处理内置的OrderedDicts,但我不确定(我没有轻松访问测试)。
旧pythons simplejson实现不能很好地处理OrderedDict对象..并在输出它们之前将它们转换为常规dicts ..但是你可以通过执行以下操作来克服这个问题:
class OrderedJsonEncoder( simplejson.JSONEncoder ):
def encode(self,o):
if isinstance(o,OrderedDict.OrderedDict):
return "{" + ",".join( [ self.encode(k)+":"+self.encode(v) for (k,v) in o.iteritems() ] ) + "}"
else:
return simplejson.JSONEncoder.encode(self, o)
现在使用这个我们得到:
>>> import OrderedDict
>>> unordered={"id":123,"name":"a_name","timezone":"tz"}
>>> ordered = OrderedDict.OrderedDict( [("id",123), ("name","a_name"), ("timezone","tz")] )
>>> e = OrderedJsonEncoder()
>>> print e.encode( unordered )
{"timezone": "tz", "id": 123, "name": "a_name"}
>>> print e.encode( ordered )
{"id":123,"name":"a_name","timezone":"tz"}
这几乎是所希望的。
另一种选择是将编码器专门用于直接使用你的行类,然后你不需要任何中间字典或UnorderedDict。
答案 2 :(得分:6)
字典的顺序与其定义的顺序没有任何关系。所有字典都是如此,而不仅仅是那些变成JSON的字典。
>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}
事实上,这本词典甚至在达到json.dumps
之前就被“颠倒了”:
>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}
答案 3 :(得分:3)
答案 4 :(得分:2)
嘿,我知道这个答案太迟了,但是添加sort_keys并为它赋false,如下所示:
json.dumps({'****': ***},sort_keys=False)
这对我有用
答案 5 :(得分:1)
json.dump() will preserve the ordder of your dictionary. Open the file in a text editor and you will see. It will preserve the order regardless of whether you send it an OrderedDict.
But json.load() will lose the order of the saved object unless you tell it to load into an OrderedDict(), which is done with the object_pairs_hook parameter as J.F.Sebastian instructed above.
It would otherwise lose the order because under usual operation, it loads the saved dictionary object into a regular dict and a regular dict does not preserve the oder of the items it is given.
答案 6 :(得分:1)
Python 3.6.1:
Python 3.6.1 (default, Oct 10 2020, 20:16:48)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> json.dumps({'b': 1, 'a': 2})
'{"b": 1, "a": 2}'
Python 2.7.5:
Python 2.7.5 (default, Nov 20 2015, 02:00:19)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> json.dumps({'b': 1, 'a': 2})
'{"a": 2, "b": 1}'
答案 7 :(得分:0)
如果您使用的是 Python 3.7+ ,它会保留顺序。
<块引用>在 Python 3.7 之前,不能保证 dict 是有序的,因此输入和输出通常被打乱,除非 collections.OrderedDict 是特别要求的。从...开始 Python 3.7,常规字典变成了顺序保留,所以它不是 不再需要为 JSON 指定 collections.OrderedDict 生成和解析。