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

使用Python/Marshmallow验证键名可变的嵌套字典

问题描述

示例数据

{
  "A-B": {
    "x": {
      "name": "x A-B"
    },
    "y": {
      "level": 6
    }
  },
  "B-C": {
    "x": {
      "name": "x B-C"
    },
    "y": {
      "level": 9
    }
  },
  "A-C": {
     "x": {
        "name": "x A-C"
    }
 }
}

数据规则

  • 顶层键为动态状态标识(如"A-B"),无固定取值范围
  • 每个状态对应的对象中,可包含x或y字段(二者均为可选),且每个字段最多出现一次
  • x字段必须是包含必填字符串类型name键的对象
  • y字段必须是包含必填整数类型level键的对象

已定义基础Schema

class X_Schema(Schema):
    name = fields.String(required=True)

class Y_Schema(Schema):
    level = fields.Integer(required=True)

现有方案的不足

当前实现需要为每个可能的状态单独定义字段,示例如下:

class StateSchema(Schema):
    a_b = fields.Dict(keys=fields.String(), values=fields.Nested(X_Schema()), required=False, data_key="A-B")
    b_c = fields.Dict(keys=fields.String(), values=fields.Nested(X_Schema()), required=False, data_key="B-C")

该方案需要枚举所有可能的状态字段,扩展性极差,无法适配未知状态标识。


解决方案

通过两层嵌套Schema即可实现动态顶层键的验证,无需枚举所有状态:

步骤1:定义单个状态对象的验证Schema

先处理每个状态对象内部的x和y字段验证:

class StateEntrySchema(Schema):
    x = fields.Nested(X_Schema(), required=False)
    y = fields.Nested(Y_Schema(), required=False)

    # 可选:如果业务要求每个状态至少包含x或y字段,添加以下验证
    @validates_schema
    def check_at_least_one_field(self, data, **kwargs):
        if not data.get("x") and not data.get("y"):
            raise ValidationError("状态对象至少需要包含x或y字段")

步骤2:定义顶层动态Schema

使用fields.Dict接收任意顶层状态键,值嵌套上述StateEntrySchema:

class StateSchema(Schema):
    __root__ = fields.Dict(
        # 可选:如果需要验证状态键格式(如必须包含"-"),添加validate规则
        keys=fields.String(validate=lambda key: "-" in key),
        values=fields.Nested(StateEntrySchema())
    )

验证示例

# 验证合法数据
data = {
    "A-B": {"x": {"name": "test"}},
    "C-D": {"y": {"level": 5}}
}
schema = StateSchema()
result = schema.load(data)
# 输出:{'__root__': {'A-B': {'x': {'name': 'test'}}, 'C-D': {'y': {'level': 5}}}}

# 验证非法数据(x缺少name)
invalid_data = {"A-B": {"x": {}}}
errors = schema.validate(invalid_data)
# 输出:{'__root__': {'A-B': {'x': {'name': ['Missing data for required field.']}}}}

该方案的优势:

  • 自动适配任意动态状态键,无需枚举
  • 严格验证x和y字段的格式要求
  • 保证每个状态对象内x和y各自最多出现一次

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:17:05