#json #jsonschema #json-schema-validator
Вопрос:
[Воспроизводится на https://www.jsonschemavalidator.net — просто скопируйте и вставьте объекты JSON (обратите внимание, что первый является примером).]
Итак, я ожидаю такой объект JSON:
[
{"k": "my_date", "v": "2021-08-04"},
{"k": "item_1", "v": 1},
{"k": "item_2", "v": 2.5},
...
{"k": ". ", "v": <<type - number>>}
]
Я хочу разработать схему JSON , которая гарантирует, что «my_date» всегда будет a string
, но все остальные элементы (независимо от их значения «k») являются числами.
То, что у меня есть сейчас, — это
{
"$id": "#/properties/my-output",
"type": "array",
"title": "The Output Schema",
"items": {
"type": "object",
"properties": {
"k": {
"type": "string"
},
"v": {
"type": "number"
}
}
}
}
но это, очевидно, не работает, так как
[
{
"k": "my_date",
"v": "2021-08-04"
},
{
"k": "any_name",
"v": 123.2
},
{
"sdf": "sdf"
}
]
терпит неудачу, потому что:
my_date
имеет значение, которое являетсяstring
, и это не разрешено схемой;sdf
здесь вообще не должно быть, но схема принимает это.
Как я должен разработать схему?
P.S. Я ожидаю, что будут и другие значения «k», которые должны иметь string
s в качестве значений «v», поэтому я хотел бы иметь возможность рассмотреть их.
Ответ №1:
Вы можете запретить использование дополнительного свойства «sdf» с "additionalProperties": false
помощью (рядом с ключевым словом «свойства»). видишь https://json-schema.org/understanding-json-schema/reference/object.html#additional-properties
Что касается ваших дат, вы, кажется, говорите, что они могут и не могут быть строками, так что я не уверен, в чем собственно проблема.
Ответ №2:
Оказалось, что в ответе используется оператор if-else-then, подобный этому (спасибо @Ether за предложение использовать additionalProperties
):
{
"$id": "#/properties/my-output",
"type": "array",
"title": "The Output Schema",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"k": {
"type": "string",
},
"v": {
}
},
"if": {
"properties": {
"k": {
"enum": ["my_date"]
}
}
},
"then": {
"properties": {
"v": {
"type": "string"
}
}
},
"else": {
"properties": {
"v": {
"type": "number"
}
}
}
}
}
Здесь происходит следующее:
Изначально мы хотим, чтобы элемент в массиве имел k
значение и v
значение. k
значение ограничено строкой — всегда; но мы не указываем ограничений для v
… пока.
Затем мы явно указываем наши ограничения: если k
это одно из "enum":["my_date", <<add others here>>]
, то мы хотим , чтобы это k
был тип string
. Еще — нам нужен номер.
Приведенная выше схема корректно завершается ошибкой при следующем тестовом вводе (который вы можете попробовать https://www.jsonschemavalidator.net):
[
{
"k": "my_date",
"v": "2021-08-04"
},
{
"k": "my_date_wrong",
"v": "2021-08-04"
},
{
"k": "some_item",
"v": 123.2
},
{
"k": "some_other_123item",
"v": 123.2
},
{
"sdf": "sdf"
}
]
Приведенный выше ввод корректно завершается "k": "my_date_wrong"
ошибкой , поскольку он не включен enum
в инструкцию if. Он также корректно выходит из строя на sdf
поле, так как он признан недействительным additionalProperties
.
Очевидным недостатком этого подхода является то, что если у вас есть много v
-s, которые должны быть строками, вам необходимо явно перечислить их в операторе if.
Ответ №3:
Таким образом, одним из подходов было бы использовать «oneOf» для схемы элементов в массиве.
{
"type": "object",
"required": ["k", "v"],
"properties": {
"k": {
"type": "string"
},
"v": {}
},
"additionalProperties": false,
"oneOf": [
{"$ref": "#/$defs/dateValue"},
{"$ref": "#/$defs/anyOtherValue"}
],
"$defs":{
"dateValue": {
"properties": {
"k": {
"const": "my_date"
},
"v": { "type": "string" }
},
"additionalProperties": false
},
"anyOtherValue": {
"not": {
"properties": {
"k": {
"enum": ["my_date"]
}
}
}
}
}
}
Комментарии:
1. (Преимущество этого подхода заключается в том, что вы можете легко распространить его на дополнительные типы ключей, добавив конкретную схему в список «oneOf» вместе со значением ключа в список «перечисление» в «любое другое значение».)