schema list validator --python cerberus

工作中需要对如下json结构进行验证:

"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.

(一)先从单条记录开始测试(cerberus_test_single.py)

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中没有错误,即验证成功。

如果修改上述文件中的document为如下:

document={
  'effectiveDates':{
    'effectiveFrom':string_toDatetime('2018-05-10'),
    'effectiveTo':string_toDatetime('2018-05-11'),
  },
  'status':'ctive',
  'reason':'Expired'
}

此时将验证失败:

E:\Learning\AWS\cerberus>cerberus_test_single.py
{'status': ['unallowed value ctive']}

 (二)加入list, 验证多条的情况:

首先想到将上述schema(红色部分)嵌套到一个schema里,然后type指定list:

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)

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在构建的时候需要使用数组[]。

posted on 2018-05-30 15:06  yanzibuaa  阅读(620)  评论(0编辑  收藏  举报