дадени:
Кажете, че дефинирам схема за контакти. Но мога да имам основен контакт, ученик или такъв, който е и двете; и различни свойства, които вървят и с трите избора. Типовете контакти са дефинирани в масив от contact_type: [ "Primary Contact", "Student" ]
, който може да бъде един или и двата.
Кажете, че полетата са като такива за тип контакт:
- Ако е основен контакт, тогава искам phone_number
- Ако Student, тогава искам 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