You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 22:45:04