我可以在json。dump中使用OrderedDict。也就是说,OrderedDict可以用作JSON的输入。
但它能被用作输出吗?如果是,怎么做?在我的情况下,我想加载到OrderedDict,这样我就可以保持文件中键的顺序。
如果不是,有没有什么解决办法?
我可以在json。dump中使用OrderedDict。也就是说,OrderedDict可以用作JSON的输入。
但它能被用作输出吗?如果是,怎么做?在我的情况下,我想加载到OrderedDict,这样我就可以保持文件中键的顺序。
如果不是,有没有什么解决办法?
当前回答
好消息!从3.6版开始,cPython实现保留了字典的插入顺序(https://mail.python.org/pipermail/python-dev/2016-September/146327.html)。这意味着json库现在默认是有序保存的。观察python 3.5和3.6之间的行为差异。代码:
import json
data = json.loads('{"foo":1, "bar":2, "fiddle":{"bar":2, "foo":1}}')
print(json.dumps(data, indent=4))
在py3.5中,结果顺序未定义:
{
"fiddle": {
"bar": 2,
"foo": 1
},
"bar": 2,
"foo": 1
}
在python 3.6的cPython实现中:
{
"foo": 1,
"bar": 2,
"fiddle": {
"bar": 2,
"foo": 1
}
}
真正的好消息是,这已经成为python 3.7的语言规范(而不是cPython 3.6+的实现细节):https://mail.python.org/pipermail/python-dev/2017-December/151283.html
所以现在问题的答案是:升级到python 3.6!:)
其他回答
是的,你可以。通过将object_pairs_hook参数指定给JSONDecoder。事实上,这正是文档中给出的示例。
>>> json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
OrderedDict([('foo', 1), ('bar', 2)])
>>>
你可以把这个参数传递给json。加载(如果你不需要Decoder实例用于其他目的),如下所示:
>>> import json
>>> from collections import OrderedDict
>>> data = json.loads('{"foo":1, "bar": 2}', object_pairs_hook=OrderedDict)
>>> print json.dumps(data, indent=4)
{
"foo": 1,
"bar": 2
}
>>>
使用json。加载的方式相同:
>>> data = json.load(open('config.json'), object_pairs_hook=OrderedDict)
除了在字典旁边转储键的有序列表外,另一个低技术含量的解决方案(具有显式的优点)是转储键-值对的有序列表ordered_dict.items();加载是一个简单的OrderedDict(<键值对列表>)。这处理了一个有序字典,尽管JSON没有这个概念(JSON字典没有顺序)。
利用json以正确的顺序转储OrderedDict这一事实确实很好。然而,作为OrderedDict(通过object_pairs_hook参数)读取所有JSON字典通常是不必要的沉重,也没有必要的意义,因此仅显式转换必须排序的字典也是有意义的。
好消息!从3.6版开始,cPython实现保留了字典的插入顺序(https://mail.python.org/pipermail/python-dev/2016-September/146327.html)。这意味着json库现在默认是有序保存的。观察python 3.5和3.6之间的行为差异。代码:
import json
data = json.loads('{"foo":1, "bar":2, "fiddle":{"bar":2, "foo":1}}')
print(json.dumps(data, indent=4))
在py3.5中,结果顺序未定义:
{
"fiddle": {
"bar": 2,
"foo": 1
},
"bar": 2,
"foo": 1
}
在python 3.6的cPython实现中:
{
"foo": 1,
"bar": 2,
"fiddle": {
"bar": 2,
"foo": 1
}
}
真正的好消息是,这已经成为python 3.7的语言规范(而不是cPython 3.6+的实现细节):https://mail.python.org/pipermail/python-dev/2017-December/151283.html
所以现在问题的答案是:升级到python 3.6!:)
除了转储字典之外,您总是可以写出键的列表,然后通过遍历列表重新构造OrderedDict ?
如果你指定了object_pairs_hook参数,通常使用的load命令将正常工作:
import json
from collections import OrderedDict
with open('foo.json', 'r') as fp:
metrics_types = json.load(fp, object_pairs_hook=OrderedDict)