基于数据的 ajv 条件模式验证

Posted

技术标签:

【中文标题】基于数据的 ajv 条件模式验证【英文标题】:ajv conditional schema validation based on data 【发布时间】:2017-08-12 01:04:39 【问题描述】:

我想根据另一个字段中的数据为一个字段指定一个正则表达式模式。这可能吗?我试过 switch 和 $data 但不知道如何使用它们。 例如,如果数据如下所示:


   "contacts":[
      
         "mode":"Email",
         "contact":"john.doe@abc.com"
      ,
      
         "mode":"Phone",
         "contact":"111-555-1234"
      
   ]

架构看起来像:

"$schema":"http://json-schema.org/draft-04/schema#",
   "type":"object",
   "properties":
      "Contacts":
         "type":"array",
         "minItems":1,
         "items":
            "type":"object",
            "properties":
               "mode":
                  "type":"string",
                  "enum":[
                     "Email",
                     "Phone"
                  ]
               ,
               "contact":
                  "type":"string",
                  "pattern":"?????"
               
            ,
            "required":[
               "mode",
               "contact"
            ]
         
      
   

如何根据模式中的数据设置联系模式,以便如果模式是电子邮件,它会根据电子邮件格式的正则表达式验证联系人,如果模式是电话,它会根据电话的正则表达式验证联系人格式?我有每个的正则表达式。我需要逻辑来选择其中一个。

【问题讨论】:

【参考方案1】:

有几种方法可以做到这一点

anyOfpros:draft-04 兼容,cons:错误报告有点冗长 - 如果出现以下情况,您会从两个子模式中得到错误没有匹配):


   "type": "object",
   "properties": 
      "Contacts": 
         "type": "array",
         "minItems": 1,
         "items": 
            "type": "object",
            "anyOf": [
               
                  "properties": 
                     "mode": "enum": ["Email"],
                     "contact": 
                        "type": "string",
                        "format": "email"
                     
                  
               ,
               
                  "properties": 
                     "mode": "enum": ["Phone"],
                     "contact": 
                        "type": "string",
                        "pattern": "phone_pattern"
                     
                  
               
            ],
            "required": ["mode", "contact"]
         
      
   

if/then/else(available in ajv-keywords package,优点:错误报告更有意义,accepted to be included in draft-07,缺点:不标准目前):


   "type": "object",
   "properties": 
      "Contacts": 
         "type": "array",
         "minItems": 1,
         "items": 
            "type": "object",
            "properties": 
               "mode": "type": "string", "enum": ["Email", "Phone"],
               "contact": "type": "string"
            ,
            "if": 
               "properties": 
                  "mode": "enum": ["Email"]
               
            ,
            "then": 
               "properties": 
                  "contact": "format": "email"
               
            ,
            "else": 
               "properties": 
                  "contact":  "pattern": "phone_pattern"
               
            
            "required": ["mode", "contact"]
         
      
   

select(available in ajv-keywords package,优点:比 if/then/else 更简洁,特别是如果有两个以上可能的值,缺点 strong>:not on the standard track yet,但你可以支持它:),需要启用 $data 引用和 Ajv v5.xx):


   "type": "object",
   "properties": 
      "Contacts": 
         "type": "array",
         "minItems": 1,
         "items": 
            "type": "object",
            "properties": 
               "mode": "type": "string",
               "contact": "type": "string"
            ,
            "select":  "$data": "0/mode" ,
            "selectCases": 
               "Email": 
                  "properties": 
                     "contact": "format": "email"
                  
               ,
               "Phone": 
                  "properties": 
                     "contact": "pattern": "phone_pattern"
                  
               
            ,
            "selectDefault": false,
            "required": ["mode", "contact"]
         
      
   

我更喜欢最后一个选项。

【讨论】:

非常有趣。根据属性之一的值,您将如何处理动态所需属性? 没关系,我想通了,这要归功于 AJV 的出色灵活性。 @Vadorequest 你能分享一下你是如何根据属性值做动态所需属性的吗?我正在寻找相同的东西。 @SantoshSidnal 我真的不记得了,那是很久以前的事了。

以上是关于基于数据的 ajv 条件模式验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 AJV 的 json 模式中的空值验证

对象数组的 AJV 模式验证

使用 ajv 验证 json 模式时获取错误类型/值

Ajv:使用动态键验证 json

为啥JOI比AJV更受欢迎?

对于具有递归$ ref的JSONSchema,ajv验证失败