Год go Я спросил , как установить тип объекта схемы на основе значения другого свойства? , на который у меня есть отличный ответ, и я с тех пор использовал эту схему.
Теперь исходные данные изменились - и схема терпит неудачу при следующих обстоятельствах:
Исходные данные содержат много свойств, однако только два из них актуальны для этого вопроса: «ключ» и «значение» - тип «значения» зависит от значения «ключ» -
Например:
Если ключ «комментарий», тип значение {"Text":"commentValue"}
.
Если ключ «смещен», тип значения равен {"seconds":int}
.
Если ключ «погодный», тип значения равен {"value": Enum["sun", "clouds", "rain"...]}
Некоторые ключи не имеют свойства value, поэтому схема должна запрещать его появление с этими ключами - например, если ключ находится в режиме ожидания, свойство value вообще не должно появляться - что и делает моя текущая схема хорошо.
Однако теперь источник данных изменился, и я получаю "value" :{}
как часть моего Json, где однажды он был опущен - и текущая схема не позволяет этого.
Так мой вопрос - как мне разрешить один из этих двух вариантов? Я пробовал любую комбинацию anyOf
, которую мог придумать, но с треском провалился - Newtonsoft.Json.Schema.JSchema
не удалось разобрать текст.
Вот упрощенная версия схемы, которую я сейчас использую:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "TestOptionalObject",
"type": "object",
"additionalProperties": false,
"required": [
"test"
],
"properties": {
"test": {
"$ref": "#/definitions/test"
}
},
"definitions": {
"test": {
"type": "object",
"required": [
"key"
],
"properties": {
"key": {
"type": "string",
"enum": [
"comment",
"offset",
"standby",
"status_unsure",
"status_ok"
]
}
},
"allOf": [
{
"if": {
"properties": {
"event": {
"enum": [
"standby",
"status_unsure",
"status_ok"
]
}
}
},
"then": {
"properties": {
"value": false
}
}
},
{
"if": {
"properties": {
"key": {
"const": "comment"
}
}
},
"then": {
"properties": {
"value": {
"$ref": "#/definitions/commentValue"
}
}
}
},
{
"if": {
"properties": {
"key": {
"const": "offset"
}
}
},
"then": {
"properties": {
"value": {
"$ref": "#/definitions/offsetValue"
}
}
}
}
]
},
"commentValue": {
"type": "object",
"additionalProperties": false,
"required": [
"text"
],
"properties": {
"text": {
"type": "string"
}
}
},
"offsetValue": {
"type": "object",
"additionalProperties": false,
"required": [
"seconds"
],
"properties": {
"seconds": {
"type": "integer",
"format": "int32"
}
}
}
}
}
Вот некоторые из вещей, которые я пробовал:
"then": {
"properties": {
"anyOf": [
{ "value": false },
{ "value": null }
]
}
}
"then": {
"anyOf": [
{
"properties": {
{ "value": false }
},
"properties": {
{ "value": null }
}
]
}
"then": {
"properties": {
"value":
"anyOf": [false, null ]
}
}
Json примеров для проверки:
В случае ошибки:
{
"test": {
"key": "comment",
"value": {"seconds":12}
}
}
{
"test": {
"key": "standby",
"value": {"asdf":12}
}
}
Должно пройти:
{
"test": {
"key": "comment",
"value": {"text":"comment text"}
}
}
{
"test": {
"key": "offset",
"value": {"seconds":12}
}
}
{
"test": {
"key": "standby"
}
}
{
"test": {
"key": "standby",
"value": {}
}
}
Обратите внимание на последний пример - свойство value
является пустым объектом - оно также должно пройти, но не с текущей схемой, поскольку value
для этого ключа свойство вообще не должно существовать.