在Python中序列化用户定义的类
我有个问题,关于我定义的类的序列化。比如我有一些类,像这样:
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 个回答
你可以考虑使用 jsonpickle 这个工具包——它的主要功能是把大部分可以被“pickle”的对象转换成json格式。
我不能给你关于JSON的建议,不过你可以使用Pickle模块把你的对象转换成二进制格式保存起来。
有几个评论。首先:
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', ']']