#json #intellisense #jsonschema #json-schema-validator
#json #intellisense #jsonschema #json-schema-validator
Вопрос:
Я пытаюсь создать схему JSON для проверки YAML для некоторого VSCode intellisense. То, что я пытаюсь сделать, это выбрать правильную подсхему для использования для свойства в основной схеме на основе значения смежного ключа.
Некоторые примеры JSON:
[
{
"name": "doesntmatter",
"matchMe": "stringToMatch:123whatever",
"mergeMe": {
"key1": "value1",
"key2": "value2"
}
}
]
[
{
"name": "doesntmatter",
"matchMe": "anotherStringToMatch:123whatever",
"mergeMe": {
"anotherKey": "valueSomething",
"anotherKey2": "cheese"
}
}
]
Поэтому мне нужно выбрать правильные схемы для mergeMe
объектов на основе соответствия подстроки matchMe
. После выполнения множества ответов я нахожусь в точке, где я могу либо сопоставить несколько, и ошибка моего линтера, либо не совпадать, но онлайн-валидатор говорит, что все в порядке (за исключением того, что ничего не совпадает, поскольку required
поля не запускаются).
Я переместил свои подсхемы для объединения, definitions
чтобы ссылаться на них, а затем использовал if / then для сопоставления. Это сработало с одним, но затем я попытался расширить его, чтобы выполнить сопоставление с деревом, и я не могу заставить это работать. Кто-то сказал, что я должен обернуть свои if / thens в allOf
(я не уверен, почему это сработает, поскольку, конечно, не все из них будут совпадать?). Изменение его на an anyOf
не приводит ни к одному из них, и я не получаю intellisense. Я также не совсем понимаю, почему я должен переносить отдельные if / thens или thens в allOf
s.
Идея заключается в том, что на основе шаблона он использует definitions
схему для соответствия mergeMe
свойству, но условная логика не совсем правильная. Уменьшенная схема ниже:
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "http://example.com/example.json",
"type": "array",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": [],
"additionalItems": true,
"definitions": {
"stringToMatch": {
"$id": "#/definitions/stringToMatch",
"type": "object",
"properties": {
"key1": {
"type": "string"
}
},
"required": [
"key1"
],
"additionalProperties": true
},
"anotherStringToMatch": {
"$id": "#/definitions/anotherStringToMatch",
"type": "object",
"properties": {
"key2": {
"type": "string"
}
},
"required": [
"key2"
],
"additionalProperties": true
}
},
"items": {
"$id": "#/items",
"type": "object",
"title": "main schema",
"description": "An explanation about the purpose of this instance.",
"default": {},
"examples": [],
"required": [
"name",
"matchMe",
"mergeMe"
],
"properties": {
"name": {
"$id": "#/items/name",
"type": "string",
"title": "The name schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": []
},
"matchMe": {
"$id": "#/items/matchMe",
"type": "string",
"title": "The matchMe schema",
"description": "An explanation about the purpose of this instance.",
"default": "",
"examples": []
}
},
"allOf": [
{
"if": {
"properties": {
"matchMe": {
"pattern": "^stringToMatch:[0-9.] "
}
}
},
"then": {
"allOf": [
{
"type": "object",
"properties": {
"mergeMe": {
"$ref": "#/definitions/stringToMatch"
}
}
}
]
}
},
{
"if": {
"properties": {
"gear": {
"pattern": "^anotherStringToMatch:[0-9.] "
}
}
},
"then": {
"allOf": [
{
"type": "object",
"properties": {
"mergeMe": {
"$ref": "#/definitions/anotherStringToMatch"
}
}
}
]
}
}
],
"additionalProperties": true
}
}
То, что я хочу в JS, будет выглядеть примерно так
const schema = { name, matchMe }
if (matchMe == "string1") schema.mergeMe = ...subschema1;
else if (...)
else if (...)
но я просто не могу с этим разобраться. Может кто-нибудь помочь?
Редактировать: игровая площадка jsonschema.dev — идея заключается в том, что если я укажу еду с префиксом «fruit», я должен дать ей «косточки» и «ягоду», тогда как если я укажу «овощ», я должен дать ему совершенно другую схему, и они не перекрываются. https://jsonschema.dev/s/pHzGo
Комментарии:
1. Действительно сложно обосновать вашу схему и экземпляр, когда вы используете нереальные значения. Пожалуйста, можете ли вы заменить свои притворные значения реальными значениями? Я знаю, это кажется глупым, но оно предоставляет контекст, который может быть полезен. Бонусные баллы, если вы можете предоставить несколько ссылок на jsonschema.dev , показывающих вашу проблему.
2. Конечно, конечно — полностью понятно. Я попытался создать небольшой пример, используя фрукты и овощи (отредактировано в нижней части вопроса).
3. Не могли бы вы привести несколько примеров экземпляров, которые не проверяются должным образом. Вы на правильном пути. Я предполагаю, что у вас просто есть несколько крайних случаев, которые нужно сгладить.
4. Боюсь, в настоящее время ни один из примеров не проверяется должным образом — они представляют собой смесь того, что у меня было на момент публикации, и того, что у меня есть на момент редактирования в ссылке jsonschema.dev, с тем, что должно быть проверено для неверной схемы. Я обнаружил, что условие «шаблон» в «если» на самом деле не соответствует, заменив ссылку на простые «обязательные», чтобы более четко видеть, что происходит.
5. На самом деле я не совсем уверен, что это вопрос json-схемы больше — когда он сведен к базовому уровню «if type is string», то () else требует чего-то — он явно проверяет ok в онлайн-валидаторах, но VSCode просто отказывается проверять свойство в блоке «if», хотязатем может потребоваться, чтобы одно и то же свойство было другого типа в следующем блоке «else».
Ответ №1:
На самом деле это оказалось ошибкой в расширении VSCode YAML, которое поглощало мою схему, в результате if
чего блоки не оценивались, и было поднято, исправлено и выпущено.