如何使用json.dumps()获取字典中的排序列表 [英] How to get sorted list inside a dictionary with json.dumps()
问题描述
我有以下问题:拥有如下所示的python字典:
I have the following problem: having a python dictionary like the following:
{"qqq": [{"bbb": "111"}, {"aaa": "333"}], "zzz": {"bbb": [5, 2, 1, 9]}}
我想获得一个有序的json对象,例如:
I would like to obtain an ordered json object such as:
'{"qqq": [{"aaa": "333"}, {"bbb": "111"}], "zzz": {"bbb": [1, 2, 5, 9]}}'
此刻我使用以下内容:
class ListEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, list):
return sorted(o)
return json.JSONEncoder.default(self, o)
print json.dumps(c, sort_keys=True, cls=ListEncoder)
但是对象内部的两个列表未排序,我得到:
But the two list inside my object are not sorted, and I get:
'{"qqq": [{"bbb": "111"}, {"aaa": "333"}], "zzz": {"bbb": [5, 2, 1, 9]}}'
可能是因为自定义JSONEncoder跳过了一种已经知道如何管理(列表)的类型.
probably because the custom JSONEncoder skips a type that already knows how to manage (list).
下面的Martijn解决方案非常适合上面的示例,但是不幸的是,我必须管理更复杂,更深入的词典:例如以下两个
Martijn solution below works perfectly for the example above, but unfortunately I have to manage more complicated dictionaries, with a bigger depth: for example the following two
a = {
'aaa': 'aaa',
'op': 'ccc',
'oppa': {
'ggg': [{'fff': 'ev'}],
'flt': {
'nnn': [
{
'mmm': [{'a_b_d': [6]},{'a_b_c': [6,7]}]
},
{
'iii': [3, 2, 4, 5]
}
]
}
},
'rrr': {},
'ttt': ['aaa-bbb-ccc']
}
b = {
'aaa': 'aaa',
'op': 'ccc',
'oppa': {
'ggg': [{'fff': 'ev'}],
'flt': {
'nnn': [
{
'iii': [2, 3, 4, 5]
},
{
'mmm': [{'a_b_c': [6,7]},{'a_b_d': [6]}]
}
]
}
},
'rrr': {},
'ttt': ['aaa-bbb-ccc']
}
如果对同一列表中的列表进行排序,它们将是相同的. 但是它们不在上面的类中,我得到了2个不同的json字符串:
They would be the same if the lists inside the same would be sorted. But they aren't with the class above, and I get 2 different json strings:
{"aaa": "aaa", "op": "ccc", "oppa": {"flt": {"nnn": [{"iii": [3, 2, 4, 1]}, {"mmm": [{"a_b_d": [6]}, {"a_b_c": [6, 7]}]}]}, "ggg": [{"fff": "ev"}]}, "rrr": {}, "ttt": ["aaa-bbb-ccc"]}
{"aaa": "aaa", "op": "ccc", "oppa": {"flt": {"nnn": [{"iii": [2, 3, 4, 5]}, {"mmm": [{"a_b_c": [6, 7]}, {"a_b_d": [6]}]}]}, "ggg": [{"fff": "ev"}]}, "rrr": {}, "ttt": ["aaa-bbb-ccc"]}
有解决此问题的主意吗?
Any idea to fix this?
推荐答案
default
不用于列表.该方法仅适用于编码器不知道如何处理的类型.改写encode
方法:
default
isn't called for lists; that method is only for types the encoder doesn't know how to handle. Override the encode
method instead:
class SortedListEncoder(json.JSONEncoder):
def encode(self, obj):
def sort_lists(item):
if isinstance(item, list):
return sorted(sort_lists(i) for i in item)
elif isinstance(item, dict):
return {k: sort_lists(v) for k, v in item.items()}
else:
return item
return super(SortedListEncoder, self).encode(sort_lists(obj))
这实际上只是在编码之前对所有列表进行排序(递归);可以在将其传递给json.dumps()
之前完成此操作,但这是编码器职责的一部分,就像对键进行排序一样.
This essentially just sorts all lists (recursively) before encoding; this could have been done before passing it to json.dumps()
but this way it is part of the responsibility of the encoder, just like sorting the keys is.
演示:
>>> json.dumps(c, sort_keys=True, cls=SortedListEncoder)
'{"qqq": [{"aaa": "333"}, {"bbb": "111"}], "zzz": {"bbb": [1, 2, 5, 9]}}'
>>> json.dumps(a, sort_keys=True, cls=SortedListEncoder)
'{"aaa": "aaa", "op": "ccc", "oppa": {"flt": {"nnn": [{"iii": [2, 3, 4, 5]}, {"mmm": [{"a_b_c": [6, 7]}, {"a_b_d": [6]}]}]}, "ggg": [{"fff": "ev"}]}, "rrr": {}, "ttt": ["aaa-bbb-ccc"]}'
>>> json.dumps(b, sort_keys=True, cls=SortedListEncoder)
'{"aaa": "aaa", "op": "ccc", "oppa": {"flt": {"nnn": [{"iii": [2, 3, 4, 5]}, {"mmm": [{"a_b_c": [6, 7]}, {"a_b_d": [6]}]}]}, "ggg": [{"fff": "ev"}]}, "rrr": {}, "ttt": ["aaa-bbb-ccc"]}'
这篇关于如何使用json.dumps()获取字典中的排序列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!