【发布时间】:2017-07-13 23:03:01
【问题描述】:
我有一组类,我想在 JSON 和 mongodb 数据库之间进行序列化。我看到的最有效的方法是编写方法来序列化为字典,然后使用内置方法来获取/从存储中获取。 (Q1:这个结论真的有效吗,还是有更好的办法?)
因此,要将我的类的实例导出到字典,我可以使用 self.dict。在我的例子中,这些类是嵌套的,所以它必须是递归的,很好。现在我想把它读回来......但是如果我的类有一个非平凡的构造函数,我会被困住。考虑:
class MyClass(object):
def __init__(self, name, value=None):
self.name = name
self._value = value
@property
def value(self):
return self._value
a = MyClass('spam', 42)
d = a.__dict__ #has {'name':'spam', '_value':42}
#now how to unserialize?
b = MyClass(**d) #nope, because '_value' is not a valid argument
c = MyClass(); c.__dict__.update(d) #nope, can't construct 'empty' MyClass
我不想编写一个忽略未知参数的构造函数,因为我讨厌浪费时间试图找出一个类忽略某些参数以发现名称中有错字的原因。而且我不想删除所需的参数,因为这可能会导致其他地方出现问题。
那么我该如何解决我为自己制造的这个烂摊子呢?
- 如果有办法绕过类的构造函数并创建一个空的
对象,这可能有效,但如果在
__init__中完成了任何有用的工作,我会失去它。 (例如,参数的类型/范围检查)。 - 在我的例子中,这些类在构造后不会改变(它们定义了很多有用的方法,并且有一些缓存)。所以如果我可以从字典中提取构造函数参数,我会做得很好。有没有不重复所有构造函数参数的方法?
【问题讨论】:
-
你最好创建工厂方法来反序列化每个类型,这样类型就可以实际控制如何构造对象。否则,您只是在外面,在您尝试填写正确的值时猜测该黑盒类型是如何工作的。 – 想象一下,如果
value属性返回self._value * 2。 -
你是否愿意接受这样的黑客攻击:ideone.com/R9T2Nd ?
-
@poke 我不明白你评论的最后一部分;只要属性/方法不改变任何属性,我为什么要关心它们进行序列化?
-
@AshwiniChaudhary 哇。覆盖
__new__绝对不是我想过的。更好的办法是让它成为一个装饰器,并在备用构造函数中获取字典。关键是object.__new__(cls)。
标签: python json serialization constructor