如果字段存在,则对规则进行两个不同的验证

时间:2019-01-03 01:34:41

标签: python validation conditional cerberus

我需要解析很多yml文件。 我有一个类似于示例的示例,其中某些情况下存在一个值,因此我需要更改另一个规则的正则表达式。 我找不到正确验证的方法

yaml1:

email: someone@company.com

yaml2:

email: otherguy@home.com
contract_type: external

模式:

schema = {
  'email': {
    'required': True,
    'type': 'string',
    'regex': '^([a-zA-Z0-9_\-\.]+)@company\.com$'
  }

1 个答案:

答案 0 :(得分:0)

快速解答(TL; DR)

  • “复合验证”方法允许有条件的(上下文感知)验证规则。
  • python cerberus软件包支持“开箱即用”的复合验证。

详细答案

上下文

  • python 2.7
  • cerberus验证包
  • jmespath查询语言(以使验证规则更紧凑和更易读)

问题

  • 开发人员NamenMalkavCreator希望应用条件验证规则。
  • 条件验证规则根据数据集中其他字段的存在或值而被激活。
  • 条件验证规则必须足够灵活,才能基于源数据中的任意状态或关系来“实时”更改。

解决方案

  • 这种方法可以通过复合数据验证来实现。
  • 在此用例下,复合验证仅意味着创建验证规则的顺序列表,例如:
    • 每个规则都对复合数据变量进行操作
    • 每条规则都为该规则适用时指定了“触发条件”
    • 每个单独的规则都会产生三个互斥的验证结果之一:validation-successvalidation-failvalidation-skipped

示例

  • 以下示例假定了多个YAML文档
  • 此处显示了一些示例文档
样本文件
aadocuments = []
aadocuments.append(yaml.safe_load('''
    person_fname:         homer
    person_lname:         himpson
    person_age:           33
    prize_caption:        free beer for life
    prize_email:          prizes@abcbooze.com
    prize_category:       alchohol
'''))
aadocuments.append(yaml.safe_load('''
    person_fname:         helen
    person_lname:         himpson
    person_age:           16
    prize_caption:        free ammo for life
    prize_email:          prizes@zzzguns.com
    prize_category:       firearms
  '''))
样本验证规则
- rule_caption:     check-underage-minor
  rule_vpath:       '[@]|[? @.person_age < `18`]'
  validation_schema:
    prize_category:
      type: string
      allowed: ['pets','toys','candy']
    prize_email:
      type:     string
      regex:    '[\w]+@.*'
  • 上面的代码是从规则列表中提取的单个验证规则的YAML格式表示。
  • 简而言之,此规则指定:
    • 如果我们遇到数据集中的一条记录,其中person_age小于18,则:
      • 声明prize_category字段存在
      • 声明prize_category字段的类型为字符串
      • 声明prize_category的值为petstoyscandy
      • 断言prize_email字段是否存在,类型为字符串
      • 声明prize_email字段与特定的正则表达式匹配

示例结果

  • 在以上示例中,helen himpson的结果为validation-fail
    • check-underage-minor验证规则将触发,因为person_age == 16
    • prize_cateogry的值为firearms,这是不允许的,因此验证失败

理性

  • 这种方法可以扩展到任意复杂程度。
  • 这种方法很容易为人类所理解(尽管jmespath语法可能是一个挑战)
  • 使用这种方法可以建立任意复杂的条件和约束条件。

陷阱

  • 上面的示例使用jmespath语法指定rule_vpath,它告诉系统仅当person_age存在且小于18时才触发此特定规则。这增加了对jmespath的依赖。 / li>

另请参见