轉自https://segmentfault.com/a/1190000011777230
Python 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
才行(注意是or
的關系)
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
類傳入的字典,稱之為模式字典
,valdiate
方法傳入的字典稱之為數據字典
。
首先,Schema
會判斷, 模式字典和數據字典的key
是否完全一樣,不一樣的話直接拋出異常。如果一樣,就去拿數據字典的value
去驗證模式字典相應的value
,如果數據字典的全部value
都可以驗證通過的話才返回數據,否則拋出異常,是不是感覺這種驗證頓時感覺清爽了呢?
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: 年齡必須是整數