根据上一个答案,我建立了一个满足我要求的方案。该问题及其答案可见here。
结果方案:
{
"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和适用于type = bus的另一个anyOf。
我将尝试更清楚地解释。有必要跟踪类型字段的值,如果它等于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
但是,正如预期的那样,该方案甚至接受了那些不应该接受的方案。
无效模式的示例。没有用于类型=总线,实体= pde的必填ID字段。没有用于类型=总线,实体=黄玉的必填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。
在这种情况下,type字段的anyOf可以正常工作。我认为这个问题是由于该方案的布局错误而再次出现的,但是我在嵌套的anyOf上找不到Internet上的信息。
当试图将所有支票插入到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"
]
}
]
}
完整JSON具有相当复杂的结构,此处仅表示一部分。因此,我想了解如何正确地构造这些东西(理解想法本身,并且最好看一看正确方案的示例。至少是示意图)。
因此,总结一下。我需要了解如何在anyOf变体之一中实现any。可行吗而且,如果是这样,我在哪里可以看到有关编译此类方案的示例和说明?如果没有,有什么解决方法吗?
答案 0 :(得分:1)
我想我已经找到了解决方案。但是,如果有任何评论或更正,我将很高兴听到。
以防万一,我举一个例子说明这个方案:
{
"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" }
}
}
}
}
}
]
}
}
}
}
答案 1 :(得分:0)
尽管嵌套的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 ...
}