Данный:
Скажем, я определяю схему для контактов. Но у меня может быть Основное Контактное лицо, Студент или тот, кто является и тем, и другим; и различные свойства, которые подходят для всех трех вариантов. Типы контактов определены в массиве contact_type: [ "Primary Contact", "Student" ]
, который может быть как одним, так и обоими.
Скажем, поля таковы для каждого типа контакта:
- Если основной контакт, то я хочу phone_number
- Если студент, то я хочу first_name
- Если студент и основное контактное лицо, мне нужны phone_number и first_name
использование
Я использую библиотеку 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
, возможно ли это? Если нет, как мне изменить схему?
Сноски
Я не хочу, чтобы contact_type был массивом, если только это не последнее средство. (это требование, но его можно нарушить, только если нет другого выхода)
Я не могу допустить никаких дополнительных элементов, поэтому я полностью определяю каждый объект в операторах if, хотя contact_type
является обычным явлением. Если я перемещаю contact_type
наружу, я получаю сообщения об ошибках о передаче contact_type
в качестве дополнительного элемента (он просматривает свойства оператора if и не видит contact_type, когда он переносится в обычное место). Вот почему мой первоначальный объект properties
пуст.
contains
не принимает объект схемы. К счастью, то, чего вы хотите, можно достичь немного другим путем. Я работаю над решением для тебя - person Relequestual   schedule 14.07.2020