Sil*_*pur 9 python serialization json
我有两个类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)
Run Code Online (Sandbox Code Playgroud)
现在,我的应用程序将构建两个列表,一个具有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])
Run Code Online (Sandbox Code Playgroud)
很显然,如果我叫json.dumps()任上list_of_...,我得到一个循环引用错误。
我想要解决这个问题的方法是转储带有元素name属性列表而不是对象本身列表的JSON :
# This is what I want to obtain for
# the JSON for list_of_As
[
{'name' : 'firstA', 'my_Bs': ['secondB']},
{'name' : 'secondA', 'my_Bs': []}
]
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一方法是在每个类中维护一个附加的字符串列表(分别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)
Run Code Online (Sandbox Code Playgroud)
如果我没记错的话,我会得到以下结果:
# 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': []}
]
Run Code Online (Sandbox Code Playgroud)
有没有更优雅的方式来获得此结果?例如,不需要任何额外的字符串列表吗?
JSONEncoder防止循环引用错误的通用类以下编码器类MyEncoder对嵌套对象执行递归编码,直到检测到循环引用为止,该循环引用将返回其“名称”属性而不是对象本身。
import json
class MyEncoder(json.JSONEncoder):
def __init__(self, *args, **argv):
super().__init__(*args, **argv)
self.proc_objs = []
def default(self, obj):
if isinstance(obj,(A,B)):
if obj in self.proc_objs:
return obj.name # short circle the object dumping
self.proc_objs.append(obj)
return obj.__dict__
return obj
json.dumps(list_of_As, cls=MyEncoder, check_circular=False, indent=2)
Run Code Online (Sandbox Code Playgroud)
输出:
[
{ "name": "firstA",
"my_Bs": [
{ "name": "secondB",
"my_As": [ "firstA" ]
}
]
},
{ "name": "secondA", "my_Bs": [] }
]
Run Code Online (Sandbox Code Playgroud)
toJSON方法您可以在类中实现序列化器方法。
[
{ "name": "firstA",
"my_Bs": [
{ "name": "secondB",
"my_As": [ "firstA" ]
}
]
},
{ "name": "secondA", "my_Bs": [] }
]
Run Code Online (Sandbox Code Playgroud)
输出:
[
{ "name": "firstA", "my_Bs": [ "secondB" ] },
{ "name": "secondA", "my_Bs": [] }
]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
359 次 |
| 最近记录: |