问题:JSON对象中的项目使用“ json.dumps”乱序了吗?
我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,名称,时区-但我却拥有时区,ID,名称。
我该如何解决?
I’m using json.dumps
to convert into json like
countries.append({"id":row.id,"name":row.name,"timezone":row.timezone})
print json.dumps(countries)
The result i have is:
[
{"timezone": 4, "id": 1, "name": "Mauritius"},
{"timezone": 2, "id": 2, "name": "France"},
{"timezone": 1, "id": 3, "name": "England"},
{"timezone": -4, "id": 4, "name": "USA"}
]
I want to have the keys in the following order: id, name, timezone – but instead I have timezone, id, name.
How should I fix this?
回答 0
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}'
请参阅PEP 468 –保留关键字参数顺序。
如果你的输入给出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)])
Both Python dict
(before Python 3.7) and JSON object are unordered collections. You could pass sort_keys
parameter, to sort the 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}'
If you need a particular order; you could 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, the keyword argument order is preserved and the above can be rewritten using a nicer syntax:
>>> json.dumps(OrderedDict(a=1, b=2))
'{"a": 1, "b": 2}'
>>> json.dumps(OrderedDict(b=2, a=1))
'{"b": 2, "a": 1}'
See PEP 468 – Preserving Keyword Argument Order.
If your input is given as JSON then to preserve the order (to get OrderedDict
), you could pass 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
正如其他人提到的那样,基本的命令是无序的。但是在python中有OrderedDict对象。(它们内置在最新的python中,或者您可以使用此代码:http : //code.activestate.com/recipes/576693/)。
我相信较新的pythons json实现可以正确处理内置的OrderedDicts,但是我不确定(而且我无法轻松访问测试)。
旧的python simplejson实现无法很好地处理OrderedDict对象..并在输出它们之前将它们转换为常规dict ..但您可以通过执行以下操作来克服这一点:
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或UnorderedDict。
As others have mentioned the underlying dict is unordered. However there are OrderedDict objects in python. ( They’re built in in recent pythons, or you can use this: http://code.activestate.com/recipes/576693/ ).
I believe that newer pythons json implementations correctly handle the built in OrderedDicts, but I’m not sure (and I don’t have easy access to test).
Old pythons simplejson implementations dont handle the OrderedDict objects nicely .. and convert them to regular dicts before outputting them.. but you can overcome this by doing the following:
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)
now using this we get:
>>> 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"}
Which is pretty much as desired.
Another alternative would be to specialise the encoder to directly use your row class, and then you’d not need any intermediate dict or UnorderedDict.
回答 2
字典的顺序与其定义的顺序没有任何关系。这对所有字典都是正确的,不仅是那些变成JSON的字典。
>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}
实际上,该字典甚至在到达之前就被“颠倒了” json.dumps
:
>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}
The order of a dictionary doesn’t have any relationship to the order it was defined in. This is true of all dictionaries, not just those turned into JSON.
>>> {"b": 1, "a": 2}
{'a': 2, 'b': 1}
Indeed, the dictionary was turned “upside down” before it even reached json.dumps
:
>>> {"id":1,"name":"David","timezone":3}
{'timezone': 3, 'id': 1, 'name': 'David'}
回答 3
嘿,我知道这个答案太迟了,但是添加sort_keys并为它赋false,如下所示:
json.dumps({'****': ***},sort_keys=False)
这对我有用
hey i know it is so late for this answer but add sort_keys and assign false to it as follows :
json.dumps({'****': ***},sort_keys=False)
this worked for me
回答 4
json.dump()将保留字典的序号。在文本编辑器中打开文件,您将看到。无论您是否发送OrderedDict,它都会保留订单。
但是json.load()会丢失已保存对象的顺序,除非您告诉它加载到OrderedDict()中,这是通过上述JFSebastian的object_pairs_hook参数完成的。
否则,它将失去顺序,因为在常规操作下,它将保存的字典对象加载到常规字典中,而常规字典不保留给出的项目的价格。
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.
回答 5
在JSON中,就像在Javascript中一样,对象键的顺序是没有意义的,因此它们按什么顺序显示实际上并不重要,它是同一对象。
in JSON, as in Javascript, order of object keys is meaningless, so it really doesn’t matter what order they’re displayed in, it is the same object.