JSON 对象中的项使用“ JSON.dump”是否无序?

我用 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-但是我使用 timezone、 id、 name。

我该怎么补救?

170265 次浏览

字典的顺序与它所定义的顺序没有任何关系。所有的字典都是如此,不仅仅是那些转换成 JSON 的字典。

>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}

事实上,这本字典甚至在到达 json.dumps之前就已经“颠倒了”:

>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}

正如其他人提到的,潜在的判决是无序的。但是在 python 中有 OrderedDect 对象。(它们是在最近的 Python 中内置的,或者您可以使用这个: http://code.activestate.com/recipes/576693/)。

我相信较新的 python json 实现能够正确地处理 OrderedDicts 中内置的内容,但是我不确定(而且我也没有容易的测试权限)。

旧的 python simplejson 实现不能很好地处理 OrderedDect 对象。.并在输出之前将它们转换成普通的发音。.但是你可以通过以下方法来克服这个问题:

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

这正是我想要的。

另一种选择是将编码器专门化以直接使用行类,这样您就不需要任何中间 dict 或 UnorderedDect。

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

如果你需要一个特定的顺序,你可以 使用 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}'

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

参见 PEP468-保留关键字参数顺序

如果输入为 JSON,那么为了保持顺序(得到 OrderedDict) ,可以传递 object_pair_hook正如@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)])

Dump ()将保留字典的顺序。在文本编辑器中打开该文件,您将看到。无论您是否向其发送 OrderedDect,它都将保留订单。

但是 json.load ()将丢失所保存对象的顺序,除非您告诉它加载到 OrderedDect ()中,而 OrderedDect ()是按照上面指示的使用 object _ tables _ hook 参数完成的。

否则它将丢失顺序,因为在通常的操作下,它将保存的字典对象加载到一个规则的 dict 中,而规则的 dict 不保留它所给出的项的顺序。

嘿,我知道这个答案已经很晚了,但是添加 sort _ key 并赋值 false,如下所示:

json.dumps({'****': ***},sort_keys=False)

这招对我很管用

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

如果您使用的是 Python 3.7 + ,那么它确实可以保持顺序。

在 Python 3.7之前,dict 不能保证是有序的,所以输入和输出通常是混乱的,除非 收集。 OrderedDect 是特别要求的。从 Python 3.7中,常规的 dict 变成了顺序保持,所以它是否定的 需要更长的时间来指定集合 生成和解析。

Https://docs.python.org/3/library/json.html#json.dump

基于麦克·安德森的答案,但是当你传入一个数组的时候也是有效的

class OrderedJsonEncoder(simplejson.JSONEncoder):
def encode(self, o, first=True):
if type(o) == list and first:
return '[' + ",".join([self.encode(val, first=False) for val in o]) + ']'
if type(o) == OrderedDict:
return "{" + ",".join(
[self.encode(k, first=False) + ":" + self.encode(v) for (k, v) in o.iteritems()]
) + "}"
else:
return simplejson.JSONEncoder.encode(self, o)