marshmallow dataclass配置exclude字段后序列化结果无法反序列化如何解决?
问题根因
- marshmallow的
exclude配置双向生效:序列化时排除指定字段输出,反序列化时也会完全忽略该字段,不会做任何赋值处理 - 你给dataclass设置了
init=False并自定义了构造函数,dataclass原生的默认值、默认工厂逻辑不会自动触发,你自定义的__init__也没有处理未传入字段的默认值初始化,导致反序列化后实例缺少被exclude的字段,抛出异常。
解决方案
直接修改基类Base的自定义__init__逻辑,补充未传入字段的默认值初始化即可,修改后的代码如下:
import uuid import dataclasses from dataclasses import dataclass, field from typing import Tuple, List, Any from marshmallow import Schema, EXCLUDE from marshmallow_dataclass import class_schema @dataclass(init=False) class Base: id: uuid.UUID = field(default=None) class Meta: ordered = True additional = ['id'] def __init__(self, **kwargs): fields = dataclasses.fields(self) names = set([f.name for f in fields]) # 处理传入的参数 for k, v in kwargs.items(): if k in names: setattr(self, k, v) # 新增:初始化未传入的字段的默认值 for f in fields: if not hasattr(self, f.name): if f.default is not dataclasses.MISSING: setattr(self, f.name, f.default) elif f.default_factory is not dataclasses.MISSING: setattr(self, f.name, f.default_factory()) # 初始化id if self.id is None: self.id = uuid.uuid4() @dataclass(init=False) class User(Base): name: str _options: List[Any] = field(default_factory=list) class Meta: unknown = EXCLUDE exclude = ['_options'] @property def options(self) -> list: return self._options @dataclass(init=False) class Person(Base): location: str _address: List[Any] = field(default_factory=list) class Meta: unknown = EXCLUDE exclude = ['_address'] user = User() user.name = 'test_user' person = Person() person.location = 'earth' user_schema = class_schema(User)() person_schema = class_schema(Person)() serialized_user = user_schema.dump(user) serialized_person = person_schema.dump(person) print(serialized_user) print(serialized_person) deserialized_user = user_schema.load(serialized_user) print(deserialized_user)
修改后反序列化时,即使被exclude的字段没有传入,也会自动用你配置的default或default_factory完成初始化,不会再抛出异常。
内容的提问来源于stack exchange,提问作者wasp256
相关产品推荐
相关产品推荐

