首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有多个嵌套anyOf的JSON模式

具有多个嵌套anyOf的JSON模式
EN

Stack Overflow用户
提问于 2019-11-11 06:08:47
回答 2查看 1.5K关注 0票数 0

根据先前的答案,我建立了一个方案,以满足我的要求。问题和答案可以看到这里

由此产生的计划:

代码语言:javascript
复制
{   
    "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:

代码语言:javascript
复制
{
    "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有路径和实体字段时。但是,如果type=io缺少路径和实体字段,节点字段看起来与上述两个字段不同。

因此,我需要有跟踪类型字段值的anyOf和另一个适用于type=bus的anyOf。

我会尽量解释得更清楚。必须跟踪类型字段的值,如果它等于总线,则会出现路径和实体字段。根据实体的值,节点字段有一个特定的结构(正是上面的图表中所写的结构)。

我尝试用嵌套的anyOf创建一个模式:

代码语言:javascript
复制
{
    "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" }
                                    }
                                }
                            }
                        }
                    }
                ]
            }
        }   
    }
} 

在站点上检查方案的示例

但一如预期,该计划甚至接受那些不应接受的计划。

无效架构的示例。对于type=bus,entity=pde,没有必需的id字段。对于type=bus,entity=topaz,没有强制的uid字段。感觉上第二个嵌套的anyOf被忽略了。

代码语言:javascript
复制
{
  "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"
        }
      ]
    }
  ]
}

检查不正确的JSON的有效性

在本例中,类型字段的anyOf按预期工作。我假设这个问题再次出现是因为方案布局错误,但是我在嵌套anyOf上找不到因特网上的信息。

当试图将所有检查插入到一个anyOf中时,一切都按预期工作。

代码语言:javascript
复制
{   
    "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" }
                                    }
                                }
                            }
                        } 
                    }
                ]
            }
        }
    }
}

但是:

  1. 这个计划看上去很肮脏
  2. 这不是我想看到的

JSON模式本身,您希望为其创建一个模式:

代码语言:javascript
复制
{
    "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变体中实现任何一个。这可行吗?若然,我在哪里可以看到编制这类计划的例子和指示呢?如果没有,有什么解决办法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-12 19:43:35

虽然嵌套anyOf在JSON中工作得很好,但我认为这不是最好的解决方案。扁平anyOf和使用一些definitions可以极大地清理模式,使其更易于推理。

代码语言:javascript
复制
{
  "$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或隐含模式而不是Enum模式,则可以获得更好的错误消息传递,但使用更复杂的模式。

代码语言:javascript
复制
{
  "$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 ...
}
票数 1
EN

Stack Overflow用户

发布于 2019-11-12 06:40:34

我想我找到了解决办法。然而,如果有任何评论或更正-我将很高兴听到。

以防万一,我举了一个由此产生的计划的例子:

代码语言:javascript
复制
{   
    "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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58796307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档