根据python中某个类列表中的值对JSON转储进行排序



我在排序JSON输出时遇到了一些问题。下面是类Rolodex,它包含两个列表条目和错误。现在输出已经正确格式化,如下所示,但我对它的排序方式有问题。

class Rolodex:
def __init__(self):
self.entries = []
self.errors = []
class Entry:
def __init__(self):
color = None
firstname = None
lastname = None
phonenumber = None
zipcode = None
def encode_rolo(obj):
if isinstance(obj, Entry):
return obj.__dict__
else:
raise TypeError("Unserializable object {} of type {}".format(obj,type(obj)))
output.write(json.dumps(rolo.__dict__, sort_keys=True, indent=4, separators=(',', ': '), default=encode_rolo).encode('utf-8'))

以下是输出(截断):

{
"entries": [
{
"color": "aqua marine",
"firstname": "Ria",
"lastname": "Tillotson",
"phonenumber": "196-910-5548",
"zipcode": "97671"
},
{
"color": "blue",
"firstname": "Annalee",
"lastname": "Loftis",
"phonenumber": "905-329-2054",
"zipcode": "97296"
},
...
],
"errors": [
1,
6,
...
]
}

正如您所看到的,条目列表中的键排序很好。但我希望能够通过(姓氏,名字)自己订购条目。有没有办法用json.dumps做到这一点?

您可以在转换为json之前通过排序来实现。

例如:

entries.sort(key=lambda e: e['lastname']+e['firstname'])

如果我理解正确,这里的问题只是Rolodex.entries是按插入顺序排列的,而不是按您希望的名称排序。您可以将该属性设置为属性,而不是当前的常规属性,并让setter在每次插入时对属性进行排序。方法如下:

class Rolodex(object):
def __init__(self):
self.errors = []
self._entries = []
@property
def entries(self):
self._entries.sort(key=lambda x: (x.lastname, x.firstname))
return self._entries

它的工作方式是,您的条目列表实际上存储在Rolodex._entries中,这是Rolodex实例的一个私有属性。现在,为了使Rolodex.entries按您的意愿工作,我们将其作为一个属性。这本质上意味着,您定义了一个方法,该方法应该在每次有东西试图访问条目时运行,当然包括json.dumps()。在这种特定的情况下,我们根据您的条件对类的私有条目列表进行排序,然后每次有任何东西访问它时都会返回。

请注意,您必须使用类从object继承此功能才能工作(这就是使用新型类的方式,无论如何,您应该养成始终从object继承的习惯。)

还要注意,这个实现效率很低,但却是我能想到的可读性最强、最容易理解的。您很可能也不需要更好的性能——但如果我在这一点上错了,您应该研究平分模块,并使用它在列表中有效地插入,您可以在我上面链接的属性文档中阅读setter方法。

最新更新