我正在使用json.dumps来转储我创建的类。有两个列表数据成员,一个从未使用过,但一个用于管理另一个数据成员列表的构建。从未使用过的列表不存在于生成的JSON中,但即使我从这些对象列表中的每个对象实例中清除了已使用的列表,也会添加该列表。我不希望JSON中有这个空列表。
在我返回要传递到转储的列表之前,我会执行以下
for entry in self.endpointList:
entry.attributeNameList.clear()
我也试着在自己的JSONEncoder中清理。当我在调试器中查看attributeNameList成员时,它们会被清除,但它们是由转储作为空数组发出的。其他未经处理的空列表永远不会显示。
另一个区别是,没有显示的空列表是以相同的方式声明的,但attributeNameList是在我的类的__init__
方法中初始化的。
class ProvisioningEndpoint:
attributeList = []
attributeNameList = []
def __init__(self, record):
self.attributeNameList = list()
有没有办法防止这个特殊的空列表被转换成
"attributeNameList": []
attributeList从未添加到JSON输出中。
从未使用过的列表和已清除的列表在调试器中看起来完全相同——为空。Python可能在列表中有一个脏比特,并使用它来决定何时作为JSON发出。谢谢
这是编码器代码(根据要求)
class ServiceRegistryEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (ProvisioningEndpoint,endpointAttribute)):
obj = obj.__dict__
您的类有两个属性,即列表attributeList
和AttributeNameList
。
类的实例具有attributeNameList
作为属性,因为它是在__init__方法中初始化的。此实例属性覆盖类属性。
您的编码器正在序列化实例的__ dict__中的所有内容,其中将包括attributeNameList
。如果你不想在self.attributeNameList
为空时串行化,那么你需要在编码器中添加一些逻辑来处理这个问题:例如:
class ServiceRegistryEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (ProvisioningEndpoint,endpointAttribute)):
obj = obj.__dict__.copy()
if not obj.get('attributeNameList):
try:
del obj['attributeNameList']
except KeyError:
pass
编辑:关于类属性的更多信息
当您尝试访问实例上的属性foo
时,Python首先查看实例的__ dict__。如果在那里找不到该属性,Python将查找实例类的__dict__。如果它在那里找到了属性,就会返回它。这意味着类的所有实例都共享类属性。有关此方面的详细信息,请参阅教程。
由于类属性在实例之间共享,对类属性的更改将对所有实例可见。这可能会导致令人惊讶或不受欢迎的行为:
>>> class Emailer(object):
... recipients = ['default@example']
... def send_secret_email(self):
... # send secret email
... pass
...
>>> e1 = Emailer()
>>> e2 = Emailer()
>>> e1.recipients.append('alice@example.com')
>>> print(e1.recipients)
['default@example', 'alice@example.com']
>>> e2.recipients.append('bob@example.com')
>>> print(e2.recipients)
['default@example', 'alice@example.com', 'bob@example.com']
>>> print(e1.recipients)
['default@example', 'alice@example.com', 'bob@example.com']
在类似上述示例的情况下,您可以在__init__方法中复制属性以减轻这种情况。
>>> class Emailer(object):
... recipients = ['default@example']
... def __init__(self):
... self.recipients = self.recipients.copy()
... def send_secret_email(self):
... # send secret email
... pass
...
>>> e1 = Emailer()
>>> e2 = Emailer()
>>> e1.recipients.append('alice@example.com')
>>> print(e1.recipients)
['default@example', 'alice@example.com']
>>> e2.recipients.append('bob@example.com')
>>> print(e2.recipients)
['default@example', 'bob@example.com']
>>> print(e1.recipients)
['default@example', 'alice@example.com']
正如@blackjack所观察到的,可变类属性通常是一种代码气味,但它们确实有一些用途:例如,如果一个类想要跟踪其实例。