工做中須要對以下json結構進行驗證:html
"ActiveStatus" : [
{
"effectiveDates" : {
"effectiveFrom" : "2018-05-10T12:44:17Z",
"effectiveTo" : "2018-05-11T00:29:29Z"
},
"status" : "Active",
"reason" : ""
},
{
"effectiveDates" : {
"effectiveFrom" : "2018-05-11T00:29:29Z"
},
"status" : "Inactive",
"reason" : "Expired/Matured"
}
],
使用cerberus, 定位到schema list.python
(一)先從單條記錄開始測試(cerberus_test_single.py)json
from cerberus import Validator from datetime import datetime, date, time def string_toDatetime(string): return datetime.strptime(string, "%Y-%m-%d") schema={ 'effectiveDates':{ 'type':'dict', 'schema':{ 'effectiveFrom':{'type':'datetime'}, 'effectiveTo':{'type':'datetime'} } }, 'status':{'type':'string','allowed':['Active','Inactive']}, 'reason':{'type':'string'} } document={ 'effectiveDates':{ 'effectiveFrom':string_toDatetime('2018-05-10'), 'effectiveTo':string_toDatetime('2018-05-11'), }, 'status':'Active', 'reason':'Expired' } v=Validator(schema) v.validate(document) print(v.errors)
在命令行運行文件,驗證成功:數組
E:\Learning\AWS\cerberus>cerberus_test.py
{}
注:結果爲{}表示v.errors中沒有錯誤,即驗證成功。dom
若是修改上述文件中的document爲以下:測試
document={ 'effectiveDates':{ 'effectiveFrom':string_toDatetime('2018-05-10'), 'effectiveTo':string_toDatetime('2018-05-11'), }, 'status':'ctive', 'reason':'Expired' }
此時將驗證失敗:spa
E:\Learning\AWS\cerberus>cerberus_test_single.py {'status': ['unallowed value ctive']}
(二)加入list, 驗證多條的狀況:命令行
首先想到將上述schema(紅色部分)嵌套到一個schema裏,而後type指定list:code
schema={ 'type':'list' schema={ 'effectiveDates':{ 'type':'dict', 'schema':{ 'effectiveFrom':{'type':'datetime'}, 'effectiveTo':{'type':'datetime'} } }, 'status':{'type':'string','allowed':['Active','Inactive']}, 'reason':{'type':'string'} } }
代碼以下(cerberus_test.py)orm
from cerberus import Validator from datetime import datetime, date, time def string_toDatetime(string): return datetime.strptime(string, '%Y-%m-%d') schema={ 'activeStatus':{ 'type':'list', 'schema':{ 'effectiveDates':{ 'type':'dict', 'schema':{ 'effectiveFrom':{'type':'datetime'}, 'effectiveTo':{'type':'datetime'} } }, 'status':{'type':'string','allowed':['Active','Inactive']}, 'reason':{'type':'string','allowed':['Expired','Matured']} } } } document={ 'activeStatus':[ { 'effectiveDates':{ 'effectiveFrom':string_toDatetime('2018-05-10'), 'effectiveTo':string_toDatetime('2018-05-11') }, 'status':'Active', 'reason':'Expired' }, { 'effectiveDates' : { 'effectiveFrom' :string_toDatetime('2018-05-11') }, 'status' : 'Inactive', 'reason' : 'Matured' } ] } v=Validator(schema) v.validate(document) print(v.errors)
命令行運行代碼發現:
E:\Learning\AWS\cerberus>cerberus_test.py Traceback (most recent call last): File "E:\Learning\AWS\cerberus\test.py", line 48, in <module> v.validate(document) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 877, in validate self.__validate_definitions(definitions, field) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 940, in __validate_definitions result = validate_rule(rule) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 922, in validate_rule return validator(definitions.get(rule, None), field, value) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 1234, in _validate_schema self.__validate_schema_sequence(field, schema, value) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 1259, in __validate_schema_sequence update=self.update, normalize=False) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 877, in validate self.__validate_definitions(definitions, field) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 940, in __validate_definitions result = validate_rule(rule) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 921, in validate_rule validator = self.__get_rule_handler('validate', rule) File "C:\Python27\lib\site-packages\cerberus\validator.py", line 338, in __get_rule_handler "domain.".format(rule, domain)) RuntimeError: There's no handler for 'status' in the 'validate' domain.
(三)解決辦法:
仔細查看cerberus自帶例子(http://docs.python-cerberus.org/en/stable/validation-rules.html#schema-list)
>>> schema = {'rows': {'type': 'list', ... 'schema': {'type': 'dict', 'schema': {'sku': {'type': 'string'}, ... 'price': {'type': 'integer'}}}}} >>> document = {'rows': [{'sku': 'KT123', 'price': 100}]} >>> v.validate(document, schema) True
發現它把schema又嵌入到一個shema裏,而不是我想的那樣,因而我這麼作:
schema={ 'activeStatus':{ 'type':'list', 'schema':{ 'schema':{ 'effectiveDates':{ 'type':'dict', 'schema':{ 'effectiveFrom':{'type':'datetime'}, 'effectiveTo':{'type':'datetime'} } }, 'status':{'type':'string','allowed':['Active','Inactive']}, 'reason':{'type':'string','allowed':['Expired','Matured']} } } } }
居然能夠成功驗證!如下爲完整的python文件(cerberus_test.py):
from cerberus import Validator from datetime import datetime, date, time #import pdb def string_toDatetime(string): return datetime.strptime(string, '%Y-%m-%d') schema={ 'activeStatus':{ 'type':'list', 'schema':{ 'schema':{ 'effectiveDates':{ 'type':'dict', 'schema':{ 'effectiveFrom':{'type':'datetime'}, 'effectiveTo':{'type':'datetime'} } }, 'status':{'type':'string','allowed':['Active','Inactive']}, 'reason':{'type':'string','allowed':['Expired','Matured']} } } } } document={ 'activeStatus':[ { 'effectiveDates':{ 'effectiveFrom':string_toDatetime('2018-05-10'), 'effectiveTo':string_toDatetime('2018-05-11') }, 'status':'Active', 'reason':'Expired' }, { 'effectiveDates' : { 'effectiveFrom' :string_toDatetime('2018-05-11') }, 'status' : 'Inactive', 'reason' : 'Matured' } ] } #pdb.set_trace() v=Validator(schema) v.validate(document) print(v.errors)
注意:由於schema是list,document在構建的時候須要使用數組[]。