Python Schema库:优雅实现数据验证的完整指南
本文详细介绍Python中Schema库的使用,解决API输入数据验证难题。通过传入类型、函数、容器及字典对象,实现简洁的数据校验。涵盖可选字段Optional的使用、忽略额外键(ignore_extra_keys)以及自定义错误信息(error参数),帮助开发者写出更优雅、健壮的后端验证代码。
Schema简介与核心概念
Schema是什么?
在任何涉及用户输入的应用开发中,都有一条核心原则:绝不信任用户提供的数据。这意味着必须对用户输入进行严格校验。在Web开发中,前端通常以JSON格式向后端API发送数据,后端API需要对这些数据进行合法性验证。以往的做法往往是堆砌大量的if判断语句,导致代码冗杂且难以维护。为了以更优雅的方式处理数据验证,Schema库应运而生。
Schema库的代码量非常精简,仅几百行,其核心逻辑主要集中在一个名为Schema的类中。
基础验证:类型与函数校验
1. 给Schema类传入类型(int、str、float等)
例如:
from schema import Schema
Schema(int).validate(10) 10 Schema(int).validate('10') SchemaUnexpectedTypeError: '10' should be instance of 'int'
由此可见,Schema会检查validate方法传入的对象是否符合指定的类型。如果类型匹配,则直接返回该数据;如果类型不匹配,则抛出SchemaError异常(其中SchemaUnexpectedTypeError是SchemaError的子类)。
2. 给Schema类传入可调用的对象(函数、带__call__的类等)
例如:
Schema(lambda x: 0<x<10).validate(5) 5 Schema(lambda x: 0<x<10).validate(57) SchemaError: <lambda>(57) should evaluate to True
可以看到,Schema会将validate方法传入的值作为参数传递给对应的函数。如果函数返回值为True,则验证通过并返回输入数据;否则抛出异常。
高级验证:内置对象与容器处理
3. 给Schema类传入带有validate方法的对象
Schema内置了一些类(如Use、And、Or等),这些类的实例均包含validate方法,也可以直接作为Schema的参数传入。例如:
from schema import Schema, And
# And代表两个条件必须同时满足 Schema(And(str, lambda s: len(s) > 2)).validate('abcd') 'abcd'
4. 给Schema类传入容器对象(list、tuple、set等)
例如:
Schema([int, float]).validate([1, 2, 3, 4.0]) [1, 2, 3, 4.0]
这表示对于列表[1, 2, 3, 4.0]中的每一个元素,它必须是int类型或者float类型(注意这里是逻辑或的关系)。
字典验证:模式与数据匹配
5. 给Schema传入一个字典对象(大部分使用Schema的场景都是传入字典对象,这个很重要)
Schema({'name': str, 'age': int}).validate({'name': 'foobar', 'age': 18}) {'age': 18, 'name': 'foobar'} Schema({'name': str, 'age': int}).validate({'name': 'foobar'}) SchemaMissingKeyError: Missing keys: 'age'
首先,需要明确两个概念:Schema类初始化时传入的字典称为“模式字典”,而validate方法中传入的字典称为“数据字典”。
验证过程首先检查模式字典和数据字典的键(key)是否完全一致。如果不一致,直接抛出异常。如果键完全一致,则取数据字典中的值去验证模式字典中对应的值类型。只有当数据字典中的所有值都通过验证时,才返回数据;否则抛出异常。这种机制使得验证过程变得清晰简洁。
常见问题:可选字段与自定义错误
6. faqs
Schema传入字典非常实用,但如果某些数据是可选的,即某些key可以不提供,该如何处理?
from schema import Optional, Schema
Schema({'name': str, Optional('age'): int}).validate({'name': 'foobar'}) {'name': 'foobar'} Schema({'name': str, Optional('age', default=18): int}).validate({'name': 'foobar'}) {'age': 18, 'name': 'foobar'}
如果希望Schema只验证传入字典中的部分数据,允许存在多余的key且不报错,应该怎么做?
Schema({'name': str, 'age': int}, ignore_extra_keys=True).validate({'name': 'foobar', 'age': 100, 'sex': 'male'}) {'age': 100, 'name': 'foobar'}
Schema抛出的异常信息有时不够友好,如何自定义错误信息?
Schema自带的类(如Use、And、Or、Regex、Schema等)都提供了一个error参数,通过该参数可以自定义错误提示信息。
Schema({'name': str, 'age': Use(int, error='年龄必须是整数')}).validate({'name': 'foobar', 'age': 'abc'})
SchemaError: 年龄必须是整数
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













