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

17

我希望为一个字段指定一个基于另一个字段中数据的正则表达式模式。这是可能的吗?我尝试过使用 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"
            ]
         }
      }
   }
}

如何根据“mode”中的数据设置联系方式的模式,使得如果“mode”是电子邮件,则验证联系方式是否符合电子邮件格式的正则表达式,如果“mode”是电话,则验证联系方式是否符合电话格式的正则表达式?我已经有每个正则表达式了,我需要选择其中一个的逻辑。

1个回答

25

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

anyOf优点:与draft-04兼容,缺点:错误报告有点冗长 - 如果没有匹配项,则会从两个子模式中都获取错误):

{
   "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(在ajv-keywords包中可用优点:错误报告更有意义,已被接受并包含在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在ajv-keywords包中可用优点:比if / then / else更简洁,特别是当有两个以上的可能值时,缺点尚未成为标准,但您可以支持它:), 需要启用 $data 参考和 Ajv v5.x.x):

{
   "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"]
         }
      }
   }
}

我更喜欢最后一个选项。


非常有趣。如果基于某个属性的值,需要动态地设置必需的属性,你会如何处理? - Vadorequest
没关系,我已经解决了,多亏了 AJV 强大的灵活性。 - Vadorequest
@Vadorequest,您能否分享一下如何根据属性的值实现动态必需属性?我正在寻找类似的东西。 - Santosh Sidnal
@SantoshSidnal,老实说我不记得了,那太久远了。 - Vadorequest
@SantoshSidnal,你找到解决方法了吗?如果是的话,请分享一下。我也在寻找同样的方法。 - Prem popatia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接