unl*_*fox 8 python marshmallow
我是第一次使用 Marshmallow,不幸的是在互联网上找不到答案。
有两个类,一个类继承另一个类。两者都应该是可序列化和可反序列化的。反序列化后,它们应该可以再次作为 Python 对象使用。因此我使用post_load装饰器。但这似乎会引起问题。在下面的最小工作示例中,我得到以下异常:type object argument after ** must be a mapping, not Bicycle。
现在可以查找该属性amount_of_tires,并在必要时传递数据。但这感觉不是正确的解决方案。
有解决这个问题的最佳实践吗?
from marshmallow import Schema, fields
from marshmallow.decorators import post_load
class Vehicle:
def __init__(self, weight):
self.weight = weight
class VehicleSchema(Schema):
weight = fields.Float()
@post_load
def make_vehicle(self, data, **kwargs) -> Vehicle:
return Vehicle(**data)
class Bicycle(Vehicle):
def __init__(self, weight, amount_of_tires):
Vehicle.__init__(self, weight=weight)
self.amount_of_tires = amount_of_tires
class BicycleSchema(VehicleSchema):
amount_of_tires = fields.Integer()
@post_load
def make_bicycle(self, data, **kwargs) -> Bicycle:
return Bicycle(**data)
my_bicycle = Bicycle(weight=10, amount_of_tires=2)
schema = BicycleSchema()
json_string = schema.dumps(my_bicycle)
deserialised_my_bicycle = schema.loads(json_string)
print(deserialised_my_bicycle)
Run Code Online (Sandbox Code Playgroud)
和make_vehicle都make_bicycle被注册为post_load钩子,因此它们会被一个接一个地调用。当make_vehicle被调用时,make_bicycle已经被调用,所以type(data) == Bicycle,因此您会看到错误。
我推荐以下解决方案:
class VehicleSchema(Schema):
model_class = Vehicle
weight = fields.Float()
@post_load
def make_vehicle(self, data, **kwargs) -> Vehicle:
return type(self).model_class(**data)
class BicycleSchema(VehicleSchema):
model_class = Bicycle
amount_of_tires = fields.Integer()
Run Code Online (Sandbox Code Playgroud)
要使用此解决方案获得更准确的类型提示 - 可以在基类上使用Generic和(请参阅https://docs.python.org/3/library/typing.html#typing.Generic)。TypeVarVehicleSchema
| 归档时间: |
|
| 查看次数: |
5008 次 |
| 最近记录: |