python - 序列化包含python中其他对象的对象的最紧凑方法?
问题描述
在python中序列化包含其他对象甚至其他对象的嵌套集合的对象的最紧凑方法是什么?
更多信息:
在我的项目中,我有我自己的类的实例集合,并且这些类中的每一个都再次包含我的其他一些类的实例的集合。
我需要使用 json 文件通过 REST api 传输其中一些集合。
我们可以使用如下示例。
示例代码:
from typing import List, Dict
class Organization:
def __init__(self, name):
self.name = name
self.employees = [] # type: List[Person]
class Person:
def __init__(self, name: str):
self.name = name
self.qualification = ""
self.pets = [] # type: List[Pet]
class Pet:
def __init__(self, name: str, species: str):
self.species = species
self.name = name
if __name__ == "__main__":
pets_dict = {"Simba": "cat", "Winnie": "bear", "Tigger": "bear", "Drogon": "dragon",
"Rhaegal": "dragon", "Viserion":"dragon", "Ghost": "wolf"}
people_dict = ["Walt", "Christopher", "Dany", "Jon"]
pets_obj = {p: Pet(p, pets_dict[p]) for p in pets_dict} # type: Dict[str, Pet]
people_obj = {p: Person(p) for p in people_dict} # type: Dict[str, Person]
people_obj["Walt"].pets = [pets_obj["Simba"],]
people_obj["Christopher"].pets = [pets_obj["Winnie"], pets_obj["Tigger"]]
people_obj["Dany"].pets = [pets_obj["Drogon"], pets_obj["Rhaegal"], pets_obj["Viserion"]]
people_obj["Jon"].pets = [pets_obj["Ghost"], ]
organization = Organization("Stories")
organization.employees = list(people_obj.values())
print(vars(organization))
输出:
{'name': 'Stories', 'employees': [<__main__.Person object at 0x00000000025DFDD8>, <__main__.Person object at 0x00000000025E6630>, <__main__.Person object at 0x00000000025E6AC8>, <__main__.Person object at 0x00000000025E6B38>]}
正如我们所见,只有对象的最高级别被序列化,而其任何集合中的对象都保持其类型。
到目前为止找到的解决方案:
有这个问答。它包含 2 个建议:第一个仅适用于简单的情况,使用
dumps(organization.__dict__)
. 这在示例情况下不起作用。第二种方法是写一个编码类,和下面的方案(2)类似。这不是一个糟糕的解决方案,但请参阅下面的“为什么我认为应该有更好的方法”。使用 json.dump(或转储)并为每个自定义类包含一个序列化程序。
def my_serializer(obj): if type(obj) in (Organization, Person, Pet): return vars(obj) else: return obj
然后做
print(dumps(organization, default=my_serializer))
- 为每个类编写一个 self.export 方法,该方法将自己序列化,并且对于它包含的任何自定义类的集合,在序列化时调用该类的导出方法。
为什么我认为应该有更好的方法:
本质上我正在寻找一个深度vars
(比如有一个deepcopy
)。我可以想象有很多人想要这样的东西,所以我希望有一个简单明了的解决方案。我只是无法通过谷歌搜索,所以我求助于社区。
解决方案
选项 2 - 将序列化程序传递给json.dumps
- 是正确的方法。您提供序列化程序,json.dumps
通过对象图递归处理。
除非您想要对象图的字典,否则没有任何价值deep_vars
,但您不需要字典,您只需要 json。