序列化包含python中其他对象的对象的最紧凑方法?

时间:2018-07-01 09:29:11

标签: python json class object serialization

在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>]}

我们可以看到,只有最高级别的对象才被序列化,而其任何集合中的对象都保持其类型。

到目前为止找到的解决方案:

  1. this question-answer。 它包含2条建议:第一条仅适用于简单情况,使用dumps(organization.__dict__)。在示例情况下,这不起作用。第二种方法是编写一个编码类,类似于下面的解决方案(2)。这不是一个糟糕的解决方案,但是请在下面查看我的“为什么我认为应该有更好的方法”。

  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))
  1. 为每个类编写一个self.export方法,该方法将对其自身进行序列化,并针对其包含的任何自定义类集合,在序列化时调用该类的export方法。

为什么我认为应该有更好的方法:

基本上,我正在寻找较深的vars(就像有一个deepcopy)。我可以想象有很多想要这样的东西的人,所以我希望有一个简单明了的解决方案。我只是无法使用Google导航,所以我转向社区。

1 个答案:

答案 0 :(得分:0)

选项2-将串行器传递给json.dumps-是执行此操作的正确方法。您提供了序列化程序,json.dumps处理对象图的递归。

除非您想要对象图的字典,否则deep_vars中没有任何值,但是您只需要json,就不需要字典。