У меня есть два класса A и B, каждый из которых хранит ссылки на объекты другого класса в списках:
class A:
def __init__(self,name):
self.name = name
self.my_Bs = []
def registerB(self,b):
self.my_Bs.append(b)
class B:
def __init__(self,name):
self.name = name
self.my_As = []
def registerA(self,a):
self.my_As.append(a)
Теперь мое приложение создает два списка, один из объектовA, один из объектов B, имеющий перекрестные ссылки.
# a list of As, a list of Bs
list_of_As = [A('firstA'), A('secondA')]
list_of_Bs = [B('firstB'), B('secondB')]
# example of one cross-reference
list_of_As[0].registerB(list_of_Bs[1])
list_of_Bs[1].registerA(list_of_As[0])
Очевидно, что если я вызову json.dumps()
для list_of_...
, я получу ошибку циклической ссылки.
ЧтоЯ хочу сделать, чтобы обойти эту проблему, чтобы сбросить JSON со списком элементов name
атрибутов вместо списков самих объектов :
# This is what I want to obtain for
# the JSON for list_of_As
[
{'name' : 'firstA', 'my_Bs': ['secondB']},
{'name' : 'secondA', 'my_Bs': []}
]
ЕдинственныйЯ могу думать о том, чтобы сохранить в каждом классе дополнительный список строк (соответственно my_Bs_names
и my_As_names
) и использовать JSONEncoder
следующим образом:
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, 'A'):
return { # filter out the list of B objects
k: v for k, v in obj.__dict__.items() if k != 'my_Bs'
}
if isinstance(obj, 'B'):
return { # filter out the list of A objects
k: v for k, v in obj.__dict__.items() if k != 'my_As'
}
return super(MyEncoder, self).default(obj)
# Use the custom encoder to dump JSON for list_of_As
print json.dumps(list_of_As, cls=MyEncoder)
Если я не ошибаюсь,Я бы получил следующий результат:
# This is what I obtain for
# the JSON for list_of_As with the code above
[
{'name' : 'firstA', 'my_Bs_names': ['secondB']},
{'name' : 'secondA', 'my_Bs_names': []}
]
Есть ли более элегантный способ получить этот результат?Например, тот, который не требует никаких дополнительных списков строк?