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

Marshmallow中实现嵌套Schema的Union类型字段需求问询

如何让Schema的Union字段支持嵌套Schema类型?

问题描述

我希望实现如下代码逻辑,让Test Schema的attr5字段能够容纳两种不同的嵌套Schema(Foo或Bar):

class Foo(Schema):
    attr1 = fds.Str(required=True)
    attr2 = fds.Int(required=True)

class Bar(Schema):
    attr3 = fds.Bool(required=True)
    attr4 = fds.Float(required=True)

class Test(Schema):
    attr5 = Union[Nested(Foo), Nested(Bar)]

但目前找到的Union实现仅支持普通数据类型,不支持嵌套Schema,请问这个需求是否可以实现?

解决方案

这个需求完全可以实现,以下是两种实用的实现方案:

方案1:自定义嵌套Union字段类

继承基础字段类,在反序列化时依次尝试用目标嵌套Schema解析数据,只要任意一个Schema验证通过即可:

from your_schema_lib import Schema, fields as fds

class Foo(Schema):
    attr1 = fds.Str(required=True)
    attr2 = fds.Int(required=True)

class Bar(Schema):
    attr3 = fds.Bool(required=True)
    attr4 = fds.Float(required=True)

class UnionNestedField(fds.Field):
    def __init__(self, schema_classes, **kwargs):
        # 初始化Schema实例
        self.schemas = [cls() for cls in schema_classes]
        super().__init__(**kwargs)
    
    def _deserialize(self, value, attr, data, **kwargs):
        validation_errors = []
        for schema in self.schemas:
            try:
                # 尝试用当前Schema加载数据
                return schema.load(value)
            except Exception as e:
                validation_errors.append(str(e))
        # 所有Schema都验证失败时抛出错误
        raise ValueError(f"数据不符合任何嵌套Schema要求: {'; '.join(validation_errors)}")

# 使用自定义字段
class Test(Schema):
    attr5 = UnionNestedField([Foo, Bar], required=True)

方案2:直接添加自定义验证函数

如果你的Schema库支持为字段指定验证函数,可以直接在attr5字段上绑定验证逻辑:

from your_schema_lib import Schema, fields as fds

class Foo(Schema):
    attr1 = fds.Str(required=True)
    attr2 = fds.Int(required=True)

class Bar(Schema):
    attr3 = fds.Bool(required=True)
    attr4 = fds.Float(required=True)

def validate_union_nested(value):
    foo_schema = Foo()
    bar_schema = Bar()
    # 先尝试用Foo解析
    try:
        return foo_schema.load(value)
    except:
        # 再尝试用Bar解析
        try:
            return bar_schema.load(value)
        except:
            raise ValueError("数据必须匹配Foo或Bar的Schema结构")

class Test(Schema):
    attr5 = fds.Field(validate=validate_union_nested, required=True)

说明

两种方案的核心逻辑一致:在加载数据时依次尝试用目标嵌套Schema解析attr5的值,只要其中一个Schema验证通过就返回解析后的对象;若所有Schema都验证失败,则抛出明确的错误提示。你可以根据使用的Schema库(如marshmallow、Pydantic等)的具体API调整细节,比如错误处理的方式、Schema实例化的逻辑等。

内容的提问来源于stack exchange,提问作者Santiago Alvarez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:30:46