元组的 cerberus 模式验证器

cerberus schema validator for tuples

我有一个变量声明如下

my_var = typing.List[typing.Tuple[int, int]]

我想写一个验证器如下

schema_validator = "my_var": {
    "type": "list",
    "empty": False,
    "items": [
        {"type": "tuple"},
        {"items": [
            {"type": "int"}, {"type": "int"}
        ]}
    ]
}

在 Cerberus 文档中,它没有为 tuples 指定验证器示例。

如何实现?

虽然这不是最干净的解决方案,但它肯定会满足您的需求。

from cerberus import Validator, TypeDefinition

class MyValidator(Validator):
    def __init__(self, *args, **kwargs):
        # Add the tuple type
        tuple_type = TypeDefinition("tuple", (tuple,), ())
        Validator.types_mapping["tuple"] = tuple_type
        # Call the Validator constructor
        super(MyValidator, self).__init__(*args, **kwargs)

    def _validate_is_int_two_tuple(self, is_int_two_tuple, field, value):
        ''' Test that the value is a 2-tuple of ints

        The rule's arguments are validated against this schema:
        {'type': 'boolean'}
        '''
        if is_int_two_tuple:
            # Check the type
            if type(value) != tuple:
                self._error(field, "Must be of type 'tuple'")
            # Check the length
            if len(value) != 2:
                self._error(field, "Tuple must have two elements")
            # Check the element types
            if type(value[0]) != int or type(value[1]) != int:
                self._error(field, "Both tuple values must be of type 'int'")

data = {"mylist": [(1,1), (2,2), (3,3)]}

schema = {
    "mylist": {
        "type": "list",
        "schema": {
            "type": "tuple",
            "is_int_two_tuple": True
        }
    }
}

v = MyValidator(schema)
print("Validated: {}".format(v.validate(data)))
print("Validation errors: {}".format(v.errors))
print("Normalized result: {}".format(v.normalized(data)))

正如 bro-grammer 指出的那样,自定义数据类型会让您验证类型,仅此而已。从您提供的架构来看,您似乎还想验证其他功能,例如元组的长度和元组中元素的类型。这样做需要的不仅仅是元组的简单 TypeDefinition

扩展验证器以包含针对此特定用例的规则并不理想,但它会满足您的要求。更全面的解决方案是创建一个 TupleValidator 子类,该子类具有验证元组长度、元素类型、顺序等的规则。

给定您的 typevar typing.List[typing.Tuple[int, int]],您期望一个任意长度的双值元组列表,其中每个值都是一个整数。

class MyValidator(Validator):
    # add a type definition to a validator subclass
    types_mapping = Validator.types_mapping.copy()
    types_mapping['tuple'] = TypeDefinition((tuple,), ())


schema = {
    'type': 'list',
    'empty': False,
    'schema': {  # the number of items is undefined
        'type': 'tuple',
        'items': 2 * ({'type': 'int'},)
    }
}

validator = MyValidator(schema)

了解 items and the schema 规则的区别很重要。

请注意,默认 list 类型实际上映射到更抽象的 Sequence type,您可能想为此添加另一个更严格的类型。