Валидация условной схемы ajv на основе данных
Я хотел бы указать шаблон регулярного выражения для одного поля на основе данных в другом. Это возможно? Я пробовал 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 ответ
Есть несколько способов сделать это
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, плюсы: отчеты об ошибках имеют больше смысла, принято для включения в черновик-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, особенно если имеется более двух возможных значений, минусы: пока не на стандартном треке, но вы можете это поддерживать:), требует включения $ ссылка на данные и 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"]
}
}
}
}
Я предпочитаю последний вариант.