JSON 具有多个嵌套 anyOf 的架构
JSON schema with multiple nested anyOf
根据之前的回答,我构建了一个满足我要求的方案。题目和答案可见.
最终方案:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type",
"path",
"entity",
"nodes"
],
"properties": {
"type": {
"type": "string"
},
"path": {
"type": "string"
},
"entity": {
"enum": ["pde", "topaz"]
}
},
"anyOf": [
{
"properties": {
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"title": "The Items Schema",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"address": {
"type": "integer"
},
"nozzles": {
"type": "array",
"items": {
"type": "integer"
}
}
}
}
}
}
},
{
"properties": {
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": {
"type": "integer"
},
"utype": {
"type": "string"
},
"uaddress": {
"type": "string"
},
"unozzles": {
"type": "boolean"
}
}
}
}
}
}
]
}
}
}
}
和JSON:
{
"virtual": [
{
"type": "bus",
"path": "VBUS1",
"entity": "pde",
"nodes": [
{
"id": "vrt_1",
"type": "dispenser",
"address": 1,
"nozzles": [1, 2, 3]
},
{
"id": "vrt_2",
"type": "dispenser",
"address": 2,
"nozzles": [4, 5, 3]
}
]
},
{
"type": "bus",
"path": "VBUS2",
"entity": "topaz",
"nodes": [
{
"uid": 1,
"utype": "dispenser",
"uaddress": "false",
"unozzles": true
},
{
"uid": 2,
"utype": "dispenser",
"uaddress": "true",
"unozzles": false
}
]
}
]
}
出现了以下问题。当 type=bus JSON 有路径和实体字段。但是,如果 type=io 路径和实体字段丢失,节点字段看起来与上面两个不同。
因此我需要有一个 anyOf 可以跟踪类型字段的值,另一个 anyOf 可以用于 type=bus。
我会尽量解释清楚。需要跟踪类型字段的值,如果它等于总线,则出现路径和实体字段。根据实体的值,节点字段具有一定的结构(正是上图中所写的)。
我试图用嵌套的 anyOf 创建一个模式:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": ["bus", "io"]
}
},
"anyOf": [
{
"properties": {
"type": {"const": "bus"},
"path": { "type": "string" },
"entity": { "enum": ["topaz", "pde"] }
},
"anyOf":[
{
"properties":{
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": { "type": "string" },
"type": { "type": "string" },
"address": { "type": "integer" },
"nozzles": {
"type": "array",
"items": { "type": "integer" }
}
}
}
}
}
},
{
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": { "type": "integer" },
"utype": { "type": "string" },
"uaddress": { "type": "string" },
"unozzles": { "type": "boolean" }
}
}
}
}
]
},
{
"properties": {
"type": {"const": "io"},
"nodes": {
"type": "array",
"items":{
"type": "object",
"required": [
"num",
"key",
"title",
"path"
],
"properties": {
"num": { "type": "integer" },
"key": { "type": "integer" },
"title": { "type": "string" },
"path": { "type": "string" }
}
}
}
}
}
]
}
}
}
}
Example of checking the scheme on the site
但不出所料,该方案甚至接受了那些不应该接受的方案。
一个无效模式的例子。 type=bus, entity=pde 没有必需的 id 字段。 type=bus、entity=topaz 没有强制性的 uid 字段。感觉第二个嵌套的anyOf被忽略了
{
"virtual": [
{
"type": "bus",
"path": "VBUS1",
"entity": "pde",
"nodes": [
{
"not_id": "vrt_1",
"type": "dispenser",
"address": 1,
"nozzles": [
1,
2,
3
]
},
{
"id": "vrt_2",
"type": "dispenser",
"address": 2,
"nozzles": [
4,
5,
3
]
}
]
},
{
"type": "bus",
"path": "VBUS2",
"entity": "topaz",
"nodes": [
{
"not_uid": 1,
"utype": "dispenser",
"uaddress": "false",
"unozzles": true
},
{
"uid": 2,
"utype": "dispenser",
"uaddress": "true",
"unozzles": false
}
]
},
{
"type": "io",
"nodes": [
{
"num": 1,
"key": 123,
"title": "123",
"path": "123"
}
]
}
]
}
Check the validity of the incorrect JSON.
在这种情况下,类型字段的 anyOf 按预期工作。估计是因为scheme布局错误又出现了这个问题,但是在网上找不到关于nested anyOf的资料。
当尝试将所有支票插入一个 anyOf 时,一切都按预期工作。
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": { "enum": ["bus", "io"] }
},
"anyOf": [
{
"properties": {
"type": {"const": "bus"},
"path": { "type": "string" },
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"title": "The Items Schema",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": { "type": "string" },
"type": { "type": "string" },
"address": { "type": "integer" },
"nozzles": {
"type": "array",
"items": { "type": "integer" }
}
}
}
}
}
},
{
"properties": {
"type": {"const": "bus"},
"path": { "type": "string" },
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": { "type": "integer" },
"utype": { "type": "string" },
"uaddress": { "type": "string" },
"unozzles": { "type": "boolean" }
}
}
}
}
},
{
"properties": {
"type": {"const": "io"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"num",
"key",
"title",
"path"
],
"properties": {
"num": { "type": "integer" },
"key": { "type": "integer" },
"title": { "type": "string" },
"path": { "type": "string" }
}
}
}
}
}
]
}
}
}
}
但是:
- 这个方案看起来很脏
- 这不是我想看到的
JSON 模式本身,您要为其创建模式:
{
"virtual": [
{
"type": "bus",
"path": "VBUS1",
"entity": "pde",
"nodes": [
{
"id": "vrt_1",
"type": "dispenser",
"address": 1,
"nozzles": [1, 2, 3]
},
{
"id": "vrt_2",
"type": "dispenser",
"address": 2,
"nozzles": [4, 5, 3]
}
]
},
{
"type": "bus",
"path": "VBUS2",
"entity": "topaz",
"nodes": [
{
"uid": 1,
"utype": "dispenser",
"uaddress": "false",
"unozzles": true
},
{
"uid": 2,
"utype": "dispenser",
"uaddress": "true",
"unozzles": false
}
]
},
{
"type": "io",
"nodes": [
"num": 4,
"key": 123456,
"title": "io",
"path": "default"
]
}
]
}
Full JSON 结构相当复杂,这里只展示了其中的一部分。因此,我想了解如何正确地构造这些东西(了解想法本身,最好看一个正确方案的例子。至少是示意图)。
所以,总结一下。我需要了解如何在其中一种 anyOf 变体中实现 any Of 。可行吗?而且,如果是这样,我在哪里可以看到编译此类方案的示例和说明?如果没有,是否有任何解决方法?
我想我找到了解决办法。但是,如果有任何意见或更正-我将很高兴听到。
以防万一我举一个结果方案的例子:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": ["bus", "io"]
}
},
"anyOf": [
{
"properties":{
"type": {"const": "bus"},
},
"anyOf":[
{
"properties":{
"path": { "type": "string" },
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": { "type": "string" },
"type": { "type": "string" },
"address": { "type": "integer" },
"nozzles": {
"type": "array",
"items": { "type": "integer" }
}
}
}
}
}
},
{
"properties":{
"path": { "type": "string" },
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": { "type": "integer" },
"utype": { "type": "string" },
"uaddress": { "type": "string" },
"unozzles": { "type": "boolean" }
}
}
}
}
}
]
},
{
"properties": {
"type": {"const": "io"},
"nodes": {
"type": "array",
"items":{
"type": "object",
"required": [
"num",
"key",
"title",
"path"
],
"properties": {
"num": { "type": "integer" },
"key": { "type": "integer" },
"title": { "type": "string" },
"path": { "type": "string" }
}
}
}
}
}
]
}
}
}
}
虽然嵌套 anyOf
在 JSON 架构中工作得很好,但我认为这不是这种情况下的最佳解决方案。展平 anyOf
并使用一些 definitions
可以极大地清理架构,使其更容易推理。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["virtual"],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": ["type"],
"anyOf": [
{ "$ref": "#/definitions/pdm" },
{ "$ref": "#/definitions/topaz" },
{ "$ref": "#/definitions/io" }
]
}
}
},
"definitions": {
"pdm": {
"properties":{
"type": { "const": "bus" },
"entity": { "const": "pde" },
... type specific properties ...
}
},
"topaz": {
"properties": {
"type": { "const": "bus" },
"entity": { "const": "topaz" },
... type specific properties ...
}
},
"io": {
"properties": {
"type": { "const": "io" },
... type specific properties ...
}
}
}
}
如果您使用 if
/then
/else
或隐含模式而不是枚举模式,您可以获得更好的错误消息,但具有更复杂的架构。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["virtual"],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": ["type"],
"allOf": [
{ "$ref": "#/definitions/pdm" },
{ "$ref": "#/definitions/topaz" },
{ "$ref": "#/definitions/io" }
]
}
}
},
"definitions": {
"pdm": {
"if": {
"properties":{
"type": { "const": "bus" },
"entity": { "const": "pde" }
},
"required": ["type", "entity"]
},
"then": {
"properties": {
... type specific constraints ...
}
}
},
... additional types ...
}
根据之前的回答,我构建了一个满足我要求的方案。题目和答案可见
最终方案:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type",
"path",
"entity",
"nodes"
],
"properties": {
"type": {
"type": "string"
},
"path": {
"type": "string"
},
"entity": {
"enum": ["pde", "topaz"]
}
},
"anyOf": [
{
"properties": {
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"title": "The Items Schema",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string"
},
"address": {
"type": "integer"
},
"nozzles": {
"type": "array",
"items": {
"type": "integer"
}
}
}
}
}
}
},
{
"properties": {
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": {
"type": "integer"
},
"utype": {
"type": "string"
},
"uaddress": {
"type": "string"
},
"unozzles": {
"type": "boolean"
}
}
}
}
}
}
]
}
}
}
}
和JSON:
{
"virtual": [
{
"type": "bus",
"path": "VBUS1",
"entity": "pde",
"nodes": [
{
"id": "vrt_1",
"type": "dispenser",
"address": 1,
"nozzles": [1, 2, 3]
},
{
"id": "vrt_2",
"type": "dispenser",
"address": 2,
"nozzles": [4, 5, 3]
}
]
},
{
"type": "bus",
"path": "VBUS2",
"entity": "topaz",
"nodes": [
{
"uid": 1,
"utype": "dispenser",
"uaddress": "false",
"unozzles": true
},
{
"uid": 2,
"utype": "dispenser",
"uaddress": "true",
"unozzles": false
}
]
}
]
}
出现了以下问题。当 type=bus JSON 有路径和实体字段。但是,如果 type=io 路径和实体字段丢失,节点字段看起来与上面两个不同。
因此我需要有一个 anyOf 可以跟踪类型字段的值,另一个 anyOf 可以用于 type=bus。
我会尽量解释清楚。需要跟踪类型字段的值,如果它等于总线,则出现路径和实体字段。根据实体的值,节点字段具有一定的结构(正是上图中所写的)。
我试图用嵌套的 anyOf 创建一个模式:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": ["bus", "io"]
}
},
"anyOf": [
{
"properties": {
"type": {"const": "bus"},
"path": { "type": "string" },
"entity": { "enum": ["topaz", "pde"] }
},
"anyOf":[
{
"properties":{
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": { "type": "string" },
"type": { "type": "string" },
"address": { "type": "integer" },
"nozzles": {
"type": "array",
"items": { "type": "integer" }
}
}
}
}
}
},
{
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": { "type": "integer" },
"utype": { "type": "string" },
"uaddress": { "type": "string" },
"unozzles": { "type": "boolean" }
}
}
}
}
]
},
{
"properties": {
"type": {"const": "io"},
"nodes": {
"type": "array",
"items":{
"type": "object",
"required": [
"num",
"key",
"title",
"path"
],
"properties": {
"num": { "type": "integer" },
"key": { "type": "integer" },
"title": { "type": "string" },
"path": { "type": "string" }
}
}
}
}
}
]
}
}
}
}
Example of checking the scheme on the site
但不出所料,该方案甚至接受了那些不应该接受的方案。
一个无效模式的例子。 type=bus, entity=pde 没有必需的 id 字段。 type=bus、entity=topaz 没有强制性的 uid 字段。感觉第二个嵌套的anyOf被忽略了
{
"virtual": [
{
"type": "bus",
"path": "VBUS1",
"entity": "pde",
"nodes": [
{
"not_id": "vrt_1",
"type": "dispenser",
"address": 1,
"nozzles": [
1,
2,
3
]
},
{
"id": "vrt_2",
"type": "dispenser",
"address": 2,
"nozzles": [
4,
5,
3
]
}
]
},
{
"type": "bus",
"path": "VBUS2",
"entity": "topaz",
"nodes": [
{
"not_uid": 1,
"utype": "dispenser",
"uaddress": "false",
"unozzles": true
},
{
"uid": 2,
"utype": "dispenser",
"uaddress": "true",
"unozzles": false
}
]
},
{
"type": "io",
"nodes": [
{
"num": 1,
"key": 123,
"title": "123",
"path": "123"
}
]
}
]
}
Check the validity of the incorrect JSON.
在这种情况下,类型字段的 anyOf 按预期工作。估计是因为scheme布局错误又出现了这个问题,但是在网上找不到关于nested anyOf的资料。
当尝试将所有支票插入一个 anyOf 时,一切都按预期工作。
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": { "enum": ["bus", "io"] }
},
"anyOf": [
{
"properties": {
"type": {"const": "bus"},
"path": { "type": "string" },
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"title": "The Items Schema",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": { "type": "string" },
"type": { "type": "string" },
"address": { "type": "integer" },
"nozzles": {
"type": "array",
"items": { "type": "integer" }
}
}
}
}
}
},
{
"properties": {
"type": {"const": "bus"},
"path": { "type": "string" },
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": { "type": "integer" },
"utype": { "type": "string" },
"uaddress": { "type": "string" },
"unozzles": { "type": "boolean" }
}
}
}
}
},
{
"properties": {
"type": {"const": "io"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"num",
"key",
"title",
"path"
],
"properties": {
"num": { "type": "integer" },
"key": { "type": "integer" },
"title": { "type": "string" },
"path": { "type": "string" }
}
}
}
}
}
]
}
}
}
}
但是:
- 这个方案看起来很脏
- 这不是我想看到的
JSON 模式本身,您要为其创建模式:
{
"virtual": [
{
"type": "bus",
"path": "VBUS1",
"entity": "pde",
"nodes": [
{
"id": "vrt_1",
"type": "dispenser",
"address": 1,
"nozzles": [1, 2, 3]
},
{
"id": "vrt_2",
"type": "dispenser",
"address": 2,
"nozzles": [4, 5, 3]
}
]
},
{
"type": "bus",
"path": "VBUS2",
"entity": "topaz",
"nodes": [
{
"uid": 1,
"utype": "dispenser",
"uaddress": "false",
"unozzles": true
},
{
"uid": 2,
"utype": "dispenser",
"uaddress": "true",
"unozzles": false
}
]
},
{
"type": "io",
"nodes": [
"num": 4,
"key": 123456,
"title": "io",
"path": "default"
]
}
]
}
Full JSON 结构相当复杂,这里只展示了其中的一部分。因此,我想了解如何正确地构造这些东西(了解想法本身,最好看一个正确方案的例子。至少是示意图)。
所以,总结一下。我需要了解如何在其中一种 anyOf 变体中实现 any Of 。可行吗?而且,如果是这样,我在哪里可以看到编译此类方案的示例和说明?如果没有,是否有任何解决方法?
我想我找到了解决办法。但是,如果有任何意见或更正-我将很高兴听到。
以防万一我举一个结果方案的例子:
{
"definitions": {},
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"virtual"
],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"enum": ["bus", "io"]
}
},
"anyOf": [
{
"properties":{
"type": {"const": "bus"},
},
"anyOf":[
{
"properties":{
"path": { "type": "string" },
"entity": {"const": "pde"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"type",
"address",
"nozzles"
],
"properties": {
"id": { "type": "string" },
"type": { "type": "string" },
"address": { "type": "integer" },
"nozzles": {
"type": "array",
"items": { "type": "integer" }
}
}
}
}
}
},
{
"properties":{
"path": { "type": "string" },
"entity": {"const": "topaz"},
"nodes": {
"type": "array",
"items": {
"type": "object",
"required": [
"uid",
"utype",
"uaddress",
"unozzles"
],
"properties": {
"uid": { "type": "integer" },
"utype": { "type": "string" },
"uaddress": { "type": "string" },
"unozzles": { "type": "boolean" }
}
}
}
}
}
]
},
{
"properties": {
"type": {"const": "io"},
"nodes": {
"type": "array",
"items":{
"type": "object",
"required": [
"num",
"key",
"title",
"path"
],
"properties": {
"num": { "type": "integer" },
"key": { "type": "integer" },
"title": { "type": "string" },
"path": { "type": "string" }
}
}
}
}
}
]
}
}
}
}
虽然嵌套 anyOf
在 JSON 架构中工作得很好,但我认为这不是这种情况下的最佳解决方案。展平 anyOf
并使用一些 definitions
可以极大地清理架构,使其更容易推理。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["virtual"],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": ["type"],
"anyOf": [
{ "$ref": "#/definitions/pdm" },
{ "$ref": "#/definitions/topaz" },
{ "$ref": "#/definitions/io" }
]
}
}
},
"definitions": {
"pdm": {
"properties":{
"type": { "const": "bus" },
"entity": { "const": "pde" },
... type specific properties ...
}
},
"topaz": {
"properties": {
"type": { "const": "bus" },
"entity": { "const": "topaz" },
... type specific properties ...
}
},
"io": {
"properties": {
"type": { "const": "io" },
... type specific properties ...
}
}
}
}
如果您使用 if
/then
/else
或隐含模式而不是枚举模式,您可以获得更好的错误消息,但具有更复杂的架构。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["virtual"],
"properties": {
"virtual": {
"type": "array",
"items": {
"type": "object",
"required": ["type"],
"allOf": [
{ "$ref": "#/definitions/pdm" },
{ "$ref": "#/definitions/topaz" },
{ "$ref": "#/definitions/io" }
]
}
}
},
"definitions": {
"pdm": {
"if": {
"properties":{
"type": { "const": "bus" },
"entity": { "const": "pde" }
},
"required": ["type", "entity"]
},
"then": {
"properties": {
... type specific constraints ...
}
}
},
... additional types ...
}