Дано:
Скажите, что я определяю схему для контактов. Но у меня может быть «Первичный контакт», «Студент» или тот, кто является обоими; и различные свойства, которые go со всеми тремя вариантами. Типы контактов определены в массиве contact_type: [ "Primary Contact", "Student" ]
, который может быть как одним, так и обоими.
Скажите, что поля соответствуют типу контакта:
- Если основной контакт , тогда мне нужен phone_number
- Если Student, то мне нужно first_name
- Если Student и основное контактное лицо, то мне нужны phone_number и first_name
Usage
Я использую библиотеку Ajv для проверки в Node.js, используя такой код:
function validator(json_schema){
const Ajv = require('ajv');
const ajv = new Ajv({allErrors: true});
return ajv.compile(json_schema)
}
const validate = validator(json_schema);
const valid = validate(input);
console.log(!!valid); //true or false
console.log(validate.errors)// object or null
Примечание: у меня были проблемы с allErrors: true
при использовании anyOf для этого, и Я использую вывод allErrors
, чтобы вернуть ВСЕ отсутствующие / недопустимые поля обратно пользователю, а не возвращать проблемы по одной. Ссылка: https://github.com/ajv-validator/ajv/issues/980
Схема
Я написал следующую схему, и она работает, если я использую либо «Студент», либо «Основное контактное лицо», но когда я прохожу оба , он по-прежнему хочет выполнить проверку по ["Студент"] или ["Основное контактное лицо"], а не по обоим.
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"required": [],
"properties": {},
"allOf": [
{
"if": {
"properties": {
"contact_type": {
"contains": {
"allOf": [
{
"type": "string",
"const": "Primary Contact"
},
{
"type": "string",
"const": "Student"
}
]
}
}
}
},
"then": {
"additionalProperties": false,
"properties": {
"contact_type": {
"type": "array",
"items": [
{
"type": "string",
"enum": [
"Student",
"Primary Contact"
]
}
]
},
"phone": {
"type": "string"
},
"first_name": {
"type": "string"
}
},
"required": [
"phone",
"first_name"
]
}
},
{
"if": {
"properties": {
"contact_type": {
"contains": {
"type": "string",
"const": "Student"
}
}
}
},
"then": {
"additionalProperties": false,
"properties": {
"contact_type": {
"type": "array",
"items": [
{
"type": "string",
"enum": [
"Student",
"Primary Contact"
]
}
]
},
"first_name": {
"type": "string"
}
},
"required": [
"first_name"
]
}
},
{
"if": {
"properties": {
"contact_type": {
"contains": {
"type": "string",
"const": "Primary Contact"
}
}
}
},
"then": {
"additionalProperties": false,
"properties": {
"contact_type": {
"type": "array",
"items": [
{
"type": "string",
"enum": [
"Student",
"Primary Contact"
]
}
]
},
"phone": {
"type": "string"
}
},
"required": [
"phone"
]
}
}
]
}
Пример допустимого ввода:
- Только для ["Основной Контакт "]:
{
"contact_type":["Primary Contact"],
"phone":"something"
}
- Только для [« Студент »]:
{
"contact_type":["Student"],
"first_name":"something"
}
- Для [« Основное контактное лицо »,» Студент "]
{
"contact_type":["Primary Contact", "Student"],
"phone":"something",
"first_name":"something"
}
Вопрос:
Я хотел бы, чтобы это подтвердилось, даже если allErrors: true
, возможно ли это? Если нет, как мне изменить схему?
Footnotes
Я не хочу менять "contact_type" на массив, если это не последнее средство. (это требование, но может быть нарушено, только если нет другого пути)
Я не могу допустить никаких дополнительных элементов, поэтому я полностью определяю каждый объект в операторах if, хотя contact_type
является обычным явлением. Если я перемещаю contact_type
, то получаю сообщения об ошибке о передаче contact_type
в качестве дополнительного элемента (он просматривает свойства оператора if и не видит contact_type, когда он переносится в обычное место). Вот почему мой начальный объект properties
пуст.