json - 有条件地合并 JSON 模式属性
问题描述
我正在尝试创建一个 JSON 模式来为某些 VSCode 智能感知验证 YAML。我要做的是根据相邻键的值选择正确的子模式以用于主模式中的属性。
一些 JSON 示例:
[
{
"name": "doesntmatter",
"matchMe": "stringToMatch:123whatever",
"mergeMe": {
"key1": "value1",
"key2": "value2"
}
}
]
[
{
"name": "doesntmatter",
"matchMe": "anotherStringToMatch:123whatever",
"mergeMe": {
"anotherKey": "valueSomething",
"anotherKey2": "cheese"
}
}
]
所以我需要mergeMe
根据matchMe
. 在遵循了一堆答案之后,我可以让它匹配多个,并错误我的 linter,或者不匹配,但是在线验证器说没关系(除了没有匹配的required
字段没有触发) .
我移动了要合并的子模式以definitions
引用它们,然后使用 if/then 进行匹配。这适用于一个,但后来我尝试扩展它以进行树匹配,但我无法让它工作。有人说我应该将我的 if/thens 包装在一个中allOf
(我不确定为什么这会起作用,因为肯定不是所有的都匹配?)。将其更改为 ananyOf
会使它们都不匹配,并且我没有智能感知。我也不明白为什么我应该在allOf
s 中包装单个 if/thens 或 thens。
这个想法是基于模式,它使用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 操场 - 如果我将食物指定为以“水果”为前缀,我必须给它“pips”和“berry”,而如果我指定“vegetable”,我必须给它一个完全不同的模式,并且它们不重叠。 https://jsonschema.dev/s/pHzGo
解决方案
这实际上最终成为 VSCode YAML 扩展中的一个错误,它正在摄取我的模式,导致if
块无法评估,并且已被提升、修复和发布。
推荐阅读
- r - 通过 tinytex 成功安装 TinyTeX 后编译 test.tex 失败
- javascript - 如何在按钮单击和滚动时更新 window.location.hash?(使用历史 API)
- python - 即使我使用了异常处理,Selenium webdriver Python 也会抛出 TimeoutException
- javascript - Angular JS级联通知
- sql - BigQuery 使用 where 子句过滤表中并不总是存在的列
- html - 是否可以逐步加载每个 CSS 文件?
- rust - 根据初始未来结果有条件地链接 Rust 未来?
- r - R:基于列名的每列不同的应用函数
- python - Scrapy ---- Error ImportError: No module named tutorial.settings
- qt - Qml中如何改变重用组件的字段?