gpt4 book ai didi

python - 序列化和反序列化用户定义类中的对象

转载 作者:行者123 更新时间:2023-12-01 09:06:49 25 4
gpt4 key购买 nike

假设我有这样的类层次结构:

class SerializableWidget(object):
# some code

class WidgetA(SerilizableWidget):
# some code

class WidgetB(SerilizableWidget):
# some code

我希望能够将 WidgetAWidgetB(以及可能的其他小部件)的实例序列化为 json 文本文件。然后,我希望能够反序列化它们,而无需事先知道它们的具体类:

some_widget = deserielize_from_file(file_path) # pseudocode, doesn't have to be exactly a method like this

some_widget需要从SerilizedWidget的精确子类构造。我该怎么做呢?我到底需要在层次结构的每个类中重写/实现哪些方法?

假设上述类的所有字段都是原始类型。如何重写一些 __to_json____from_json__ 方法,诸如此类?

最佳答案

您可以通过多种方法解决此问题。一个示例是分别对 json.loadjson.dump 使用 object_hookdefault 参数。

您所需要的只是将类与对象的序列化版本存储在一起,然后在加载时您必须使用哪个类与哪个名称对应的映射。

下面的示例使用 dispatcher 类装饰器在序列化时存储类名和对象,并在稍后反序列化时查找它。您所需要的只是每个类上的 _as_dict 方法来将数据转换为字典:

import json

@dispatcher
class Parent(object):
def __init__(self, name):
self.name = name

def _as_dict(self):
return {'name': self.name}


@dispatcher
class Child1(Parent):
def __init__(self, name, n=0):
super().__init__(name)
self.n = n

def _as_dict(self):
d = super()._as_dict()
d['n'] = self.n
return d

@dispatcher
class Child2(Parent):
def __init__(self, name, k='ok'):
super().__init__(name)
self.k = k

def _as_dict(self):
d = super()._as_dict()
d['k'] = self.k
return d

现在进行测试。首先让我们创建一个包含 3 个不同类型的对象的列表。

>>> obj = [Parent('foo'), Child1('bar', 15), Child2('baz', 'works')]

序列化它将产生每个对象中带有类名的数据:

>>> s = json.dumps(obj, default=dispatcher.encoder_default)
>>> print(s)
[
{"__class__": "Parent", "name": "foo"},
{"__class__": "Child1", "name": "bar", "n": 15},
{"__class__": "Child2", "name": "baz", "k": "works"}
]

加载它会生成正确的对象:

obj2 = json.loads(s, object_hook=dispatcher.decoder_hook)
print(obj2)
[
<__main__.Parent object at 0x7fb6cd561cf8>,
<__main__.Child1 object at 0x7fb6cd561d68>,
<__main__.Child2 object at 0x7fb6cd561e10>
]

最后,这是调度程序的实现:

class _Dispatcher:
def __init__(self, classname_key='__class__'):
self._key = classname_key
self._classes = {} # to keep a reference to the classes used

def __call__(self, class_): # decorate a class
self._classes[class_.__name__] = class_
return class_

def decoder_hook(self, d):
classname = d.pop(self._key, None)
if classname:
return self._classes[classname](**d)
return d

def encoder_default(self, obj):
d = obj._as_dict()
d[self._key] = type(obj).__name__
return d
dispatcher = _Dispatcher()

关于python - 序列化和反序列化用户定义类中的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51975664/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com