在Python中序列化用户定义的类

3 投票
3 回答
1420 浏览
提问于 2025-04-16 06:30

我有个问题,关于我定义的类的序列化。比如我有一些类,像这样:

class Foo:
     def __init__(self, x, y):
          self.x = x, self.y = y

     def toDict(self):
          return dict(Foo = dict(x = self.x, y = self.y))

然后还有一个类可以包含多个Foo,像这样:

class Bar:
     def __init__(self):
          self.foos = [Foo(a, b), Foo(1, 2)]

虽然这只是对实际结构的一个非常简单的概述(实际上结构要复杂得多),但大致上是这样的。实际的数据来自一个伪XML文件,没有任何实际的结构,所以我根据给我的规范写了一个解析器,现在我把所有数据都放在我定义的一系列类里,形成了实际的结构。

我想做的是把这些数据转换成JSON格式,但我真的不知道该怎么做(我刚开始学Python,这是我用它做的第一个真正的项目)。

我在Foo类里定义了一个方法toDict(),可以把信息变成一个字典,但当我尝试序列化包含多个Foo的Bar时,这显然不会像我希望的那样工作。

有没有人有好的办法来解决这个问题?这几天我几乎一直在学习和写代码,现在对这个问题没有任何想法了,而这是项目的最后一部分。我知道Python有一个JSON模块,但这对我把数据转换成字典(或类似的东西)以便传递给json.dump()这个特定问题没有帮助。

如果我能进一步解释,请告诉我。

谢谢,
T.J.

3 个回答

0

你可以考虑使用 jsonpickle 这个工具包——它的主要功能是把大部分可以被“pickle”的对象转换成json格式。

0

我不能给你关于JSON的建议,不过你可以使用Pickle模块把你的对象转换成二进制格式保存起来。

5

有几个评论。首先:

  • xml.dom.minidom 是 Python 自带的一个 DOM 实现。如果你的文件其实不是 XML 格式,那你就不能用它自带的解析功能。不过,看起来你还是在从文件中构建一个树状结构,这样的话,你不如直接用 minidom

好的,从现在开始,我就假设你有很好的理由去写自己的树状结构,而不是使用内置的。

  • 你确定节点应该是类吗?这看起来结构有点复杂,其实你可能只需要一堆嵌套的 dict(字典):

    root = {
        "foo1": { "bar1": "spam", "bar2": "ham"},
        "foo2": { "baz1": "spam", "baz2": "ham"},
    }
    

    你明白我的意思了。

好的,也许你确实认为每个节点都需要是类。在这种情况下,它们应该都继承自某个 BaseNode 类,对吧?毕竟,它们本质上是相似的东西。

  • 那么,定义一个 BaseNode.serialise 方法,这个方法可以打印出一些关于它自己的信息,然后调用所有子节点的 serialise 方法。这是一个递归问题;除非你的树真的非常非常嵌套,否则你可以使用递归的解决方案。

    json 库允许你对 JSONEncoder 进行子类化来实现这个功能。

    >>> import json
    >>> class ComplexEncoder(json.JSONEncoder):
    ...     def default(self, obj):
    ...         if isinstance(obj, complex):
    ...             return [obj.real, obj.imag]
    ...         return json.JSONEncoder.default(self, obj)
    ...
    >>> dumps(2 + 1j, cls=ComplexEncoder)
    '[2.0, 1.0]'
    >>> ComplexEncoder().encode(2 + 1j)
    '[2.0, 1.0]'
    >>> list(ComplexEncoder().iterencode(2 + 1j))
    ['[', '2.0', ', ', '1.0', ']']
    

撰写回答