schema list validator --python cerberus

工做中須要對以下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在構建的時候須要使用數組[]。

相關文章
相關標籤/搜索