Python Schema使用說明
專案地址:GitHub
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: 年齡必須是整數