Вот моя JSON схема (гипотетическая, поскольку я не могу поделиться своей фактической) и JSON. Условие if-then-else выглядит следующим образом:
одновременно может появиться только одна (1) из трех (3) стран для определения статистики.
Схема
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"year",
"country",
"statistics"
],
"definitions": {
"statisticsUsa": {
"if": {
"properties": {
"type": {
"const": "statisticsUsa"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"type": {
"const": "statisticsUsa"
}
}
}
},
"statisticsFinland": {
"if": {
"properties": {
"type": {
"const": "statisticsFinland"
}
},
"required": [
"type"
]
},
"then": {
"properties": {
"type": {
"const": "statisticsFinland"
}
}
}
},
"statisticsGermany": {
"if": {
"properties": {
"type": {
"const": "statisticsGermany"
}
},
"required": [
"type", "literacy"
]
},
"then": {
"properties": {
"type": {
"const": "statisticsGermany"
},
"literacy": {
"type": "string"
}
}
}
}
},
"properties": {
"year": {
"type": "string"
},
"country": {
"type": "string",
"enum": [
"USA",
"FINLAND",
"GERMANY"
]
},
"statistics": {
"type": "array",
"allOf": [{
"if": {
"contains": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"statisticsUsa"
]
}
}
}
},
"then": {
"not": {
"contains": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"statisticsFinland",
"statisticsGermany"
]
}
}
}
}
},"errorMessage" :"Only USA applicable at a time for statistics"
},
{
"if": {
"contains": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"statisticsFinland"
]
}
}
}
},
"then": {
"not": {
"contains": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"statisticsUsa",
"statisticsGermany"
]
}
}
}
}
},"errorMessage" :"Only Finland applicable at a time for statistics"
},
{
"if": {
"contains": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"statisticsGermany"
]
}
}
}
},
"then": {
"not": {
"contains": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"statisticsUsa",
"statisticsFinland"
]
}
}
}
}
},"errorMessage" :"Only Germany applicable at a time for statistics"
}
],
"minItems": 1,
"items": {
"anyOf": [{
"$ref": "#/definitions/statisticsUsa"
},
{
"$ref": "#/definitions/statisticsFinland"
},
{
"$ref": "#/definitions/statisticsGermany"
}
]
}
}
}
}
Json 1
const Ajv = require('ajv');
const ajv = new Ajv({
allErrors: true,
jsonPointers: true
});
const schema1 = require("./sof.json");
require('ajv-errors')(ajv /*, {singleError: true} */);
const data = {
year: "2000",
country: "USA",
statistics: [
{"type":"statisticsUsa"},
{"type":"statisticsFinland"}
]
}
let valid = ajv.validate(schema1, data); //schema, data
if (!valid) {
console.log(`${JSON.stringify(ajv.errors,null,2)}`);
}
Здесь я вижу 2 ошибки как часть массива, когда у меня 2 страны. Мой вопрос заключается в том, что, будучи «финляндия» не может иметь отношения с «США», ошибка «Только США применима одновременно для статистики» НЕ является приемлемой, поскольку она удовлетворяет условию. Но, ошибка для Findland является приемлемой.
[
{
"keyword": "errorMessage",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/0/errorMessage",
"params": {
"errors": [
{
"keyword": "not",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/0/then/not",
"params": {},
"message": "should NOT be valid"
},
{
"keyword": "if",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/0/if",
"params": {
"failingKeyword": "then"
},
"message": "should match \"then\" schema"
}
]
},
"message": "Only USA applicable at a time for statistics"
},
{
"keyword": "errorMessage",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/1/errorMessage",
"params": {
"errors": [
{
"keyword": "not",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/1/then/not",
"params": {},
"message": "should NOT be valid"
},
{
"keyword": "if",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/1/if",
"params": {
"failingKeyword": "then"
},
"message": "should match \"then\" schema"
}
]
},
"message": "Only Finland applicable at a time for statistics"
}
]
Кроме того, если я добавлю 'Germany' в JSON as,
{
year: "2000",
country: "USA",
statistics: [
{"type":"statisticsUsa"},
{"type":"statisticsFinland"},
{"type":"statisticsGermany"}
]
}
, она выдаст 3 ошибки как часть массива (См. ниже). Почему?
- Технически, валидатор схемы должен остановиться на 2-м элементе и должен игнорировать «Германия» в массиве ошибок, так как обнаруживает, что запись «Findland» нарушает условия if-else.
- Кроме того, проверяет ли схема-валидатор каждый элемент из массива статистики (из JSON) и проверяет условия в 'allOf' для каждого запуска, и поэтому 3 записи об ошибках в массиве. Правильно ли мое понимание. (Если вы видите первый массив ошибок выше, он имеет только 2 записи)
[
{
"keyword": "errorMessage",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/0/errorMessage",
"params": {
"errors": [
{
"keyword": "not",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/0/then/not",
"params": {},
"message": "should NOT be valid"
},
{
"keyword": "if",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/0/if",
"params": {
"failingKeyword": "then"
},
"message": "should match \"then\" schema"
}
]
},
"message": "Only USA applicable at a time for statistics"
},
{
"keyword": "errorMessage",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/1/errorMessage",
"params": {
"errors": [
{
"keyword": "not",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/1/then/not",
"params": {},
"message": "should NOT be valid"
},
{
"keyword": "if",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/1/if",
"params": {
"failingKeyword": "then"
},
"message": "should match \"then\" schema"
}
]
},
"message": "Only Finland applicable at a time for statistics"
},
{
"keyword": "errorMessage",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/2/errorMessage",
"params": {
"errors": [
{
"keyword": "not",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/2/then/not",
"params": {},
"message": "should NOT be valid"
},
{
"keyword": "if",
"dataPath": "/statistics",
"schemaPath": "#/properties/statistics/allOf/2/if",
"params": {
"failingKeyword": "then"
},
"message": "should match \"then\" schema"
}
]
},
"message": "Only Germany applicable at a time for statistics"
}
]