json.dumps()对除顶级之外的键进行排序



需要转储对象的dict。我想对嵌套对象的键进行排序,同时保留顶级键的顺序。以下对所有密钥进行排序:

json.dumps(dict_of_objs, sort_keys=True, default=vars)    

感谢


坏解决方案

我可以运行以下程序,但这似乎是很多不必要的处理:

for key in dict_of_objs.keys():
sorted_str = json.dumps(dict_of_objs[key], sort_keys=True, default=vars)
dict_of_objs[key] = json.loads(sorted_str)
json.dumps(dict_of_objs)    

我的解决方案我认为它与您的解决方案相同,但我认为您可以使lt返回False。

from json import JSONEncoder

class WrappedDict(dict):
def items(self):
# https://github.com/python/cpython/blob/main/Lib/json/encoder.py#L353
# Return our wrapped items to sorted.
return (WrappedItem(item) for item in super().items())

class WrappedItem(tuple):
def __lt__(self, other):
# https://docs.python.org/3/library/functions.html#sorted
# Fake out sorted by just saying no item, ie. (k, v), is ever less than.
return False
root = {
"b": 2,
"a": 1,
"c": {
"b": 2,
"a": [{
"z": 15,
"a": 1,
}]
}
}
wrapped_root = WrappedDict(root)

print ('root')
print (root)
print ('sort_keys=True with wrapped root')
print (JSONEncoder(sort_keys=True).encode(wrapped_root))
print ('sort_keys=True with root')
print (JSONEncoder(sort_keys=True).encode(root))
print ('sort_keys=False with wrapped_root')
print (JSONEncoder(sort_keys=False).encode(wrapped_root))
print ('sort_keys=False with root')
print (JSONEncoder(sort_keys=False).encode(root))

输出

root
{'b': 2, 'a': 1, 'c': {'b': 2, 'a': [{'z': 15, 'a': 1}]}}
sort_keys=True with wrapped root
{"b": 2, "a": 1, "c": {"a": [{"a": 1, "z": 15}], "b": 2}}
sort_keys=True with root
{"a": 1, "b": 2, "c": {"a": [{"a": 1, "z": 15}], "b": 2}}
sort_keys=False with wrapped_root
{"b": 2, "a": 1, "c": {"b": 2, "a": [{"z": 15, "a": 1}]}}
sort_keys=False with root
{"b": 2, "a": 1, "c": {"b": 2, "a": [{"z": 15, "a": 1}]}}
编辑

评论指出,不需要知道键的值,我们可以通过让lt始终返回False:来完全禁用排序

#!/usr/bin/env python3
import json
class UnSortableString(str):
def __lt__(self, other):
return False
normal_dict = {"zzz" : [5,4,3], "aaa": [100,3] }
print(json.dumps(normal_dict, sort_keys=True))
mydict = {UnSortableString("zzz") : [5,4,3], UnSortableString("aaa"): [100,3] }
print(json.dumps(mydict, sort_keys=True))

输出:

{"aaa": [100, 3], "zzz": [5, 4, 3]}
{"zzz": [5, 4, 3], "aaa": [100, 3]}

因为在我的情况下,我知道顶级密钥的值,所以我想出了以下破解解决方案:

#!/usr/bin/env python3
import json
class FakeString(str):
order = ["first", "second", "last"]
def __lt__(self, other):
if self in FakeString.order and other in FakeString.order:
return FakeString.order.index(self) < FakeString.order.index(other)
return super.__lt__(self, other) 
normal_dict = {"last" : [5,4,3], "second": [100,3] }
print(json.dumps(normal_dict, sort_keys=True))
mydict = {FakeString("last") : [5,4,3], FakeString("second"): [100,3] }
print(json.dumps(mydict, sort_keys=True))

输出:

{"last": [5, 4, 3], "second": [100, 3]}
{"second": [100, 3], "last": [5, 4, 3]}

最新更新