Python Schema一種優雅的數據驗證方式

Python Schema使用說明

項目地址:GitHubpython

Schema是什麼?

無論咱們作什麼應用,只要和用戶輸入打交道,就有一個原則--永遠不要相信用戶的輸入數據。意味着咱們要對用戶輸入進行嚴格的驗證,web開發時通常輸入數據都以JSON形式發送到後端API,API要對輸入數據作驗證。通常我都是加不少判斷,各類if,致使代碼很醜陋,能不能有一種方式比較優雅的驗證用戶數據呢?Schema就派上用場了。git

Schema很是簡單,也就幾百行的代碼,最核心的類就一個:Schemagithub

1. 給Schema類傳入類型(intstrfloat等)

例如:web

from schema import Schema

Schema(int).validate(10)
10
Schema(int).validate('10')
SchemaUnexpectedTypeError: '10' should be instance of 'int'

可見Schema會去驗證validate方法傳入的對象是否是所指定的類型,是則返回傳入的數據,不然拋出一個SchemaError的異常(SchemaUnexpectedTypeErrorSchemaError的子類)。後端

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則返回輸入數據,不然拋出異常。lua

3. 給Schema類傳入帶有validate方法的對象

Schema也內置了一些類(UseAndOr等等),這些類的實例都帶有validate方法,亦可做爲Schema的參數傳入,例如:code

from schema import Schema, And

# And表明兩個條件必須同時知足
Schema(And(str, lambda s: len(s) > 2)).validate('abcd')
'abcd'

4. 給Schema類傳入容器對象(listtupleset等)

例如:對象

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

  1. 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'}
  1. 我想讓Schema只驗證傳入字典中的一部分數據,能夠有多餘的key可是不要抱錯,怎麼作?
Schema({'name': str, 'age': int}, ignore_extra_keys=True).validate({'name': 'foobar', 'age': 100, 'sex': 'male'})
{'age': 100, 'name': 'foobar'}
  1. Schema拋出的異常信息不是很友好,我想自定義錯誤信息,怎麼辦?

Schema自帶的類(UseAndOrRegexSchema等)都有一個參數error,能夠自定義錯誤信息

Schema({'name': str, 'age': Use(int, error='年齡必須是整數')}).validate({'name': 'foobar', 'age': 'abc'})
SchemaError: 年齡必須是整數
相關文章
相關標籤/搜索