JSON模式错误地成功验证 [英] Erroneous successful validation by JSON-schema

查看:92
本文介绍了JSON模式错误地成功验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

节点中的字段取决于实体的值.也就是说,如果entity ="pd",则节点具有一些字段,而entity ="top"-节点具有完全不同的字段,尽管实际上是严格要求的.由于某种原因,即使在节点中未按要求定义字段,有效模式也会接受JSON字符串.我已经全神贯注,大多数方案中哪里会出错? JSON模式:

The fields in nodes depend on the value of entity. That is, if entity = "pd", then nodes has some fields, while entity = " top " - nodes has completely different fields, despite the fact that they are strictly required. For some reason, the JSON string is accepted by the valid schema, even if there are no fields defined in nodes as required. I already entire head broke, where can be mistake in the most scheme? JSON-schema:

{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "virtual"
  ],
  "properties": {
    "virtual": {
      "$id": "#/properties/virtual",
      "type": "array",
      "title": "The Virtual Schema",
      "items": {
        "$id": "#/properties/virtual/items",
        "type": "object",
        "title": "The Items Schema",
        "required": [
          "type",
          "path",
          "entity",
          "nodes"
        ],
        "properties": {
          "type": {
            "$id": "#/properties/virtual/items/properties/type",
            "type": "string",
            "title": "The Type Schema",
            "default": "",
            "examples": [
              "bus"
            ],
            "pattern": "^(.*)$"
          },
          "path": {
            "$id": "#/properties/virtual/items/properties/path",
            "type": "string",
            "title": "The Path Schema",
            "default": "",
            "examples": [
              "VBUS2"
            ],
            "pattern": "^(.*)$"
          },
          "entity": {
            "$id": "#/properties/virtual/items/properties/entity",
            "type": "string",
            "title": "The Entity Schema",
            "default": "",
            "examples": [
              "topaz"
            ],
            "enum": ["pde", "topaz"],
            "pattern": "^(.*)$"
          },
          "nodes": {
            "$id": "#/properties/virtual/items/properties/nodes",
            "type": "array",
            "title": "The Nodes Schema",
            "items": {
                "$id": "#/properties/virtual/items/properties/nodes/items",
                "type": "object",
                "title": "The Items Schema"
            }
          }
        }
      }
    }
  },
  "anyOf": [
    {       
        "if": {
            "properties": { "virtual": { "properties": { "entity": { "const": "topaz" } } } } 
        },
        "then": {
            "properties": { 
                "virtual": { 
                    "properties": { 
                        "nodes": {  
                            "items": {
                                "required": [
                                    "uid",
                                    "utype",
                                    "uaddress",
                                    "unozzles"
                                ],
                                "properties": {
                                    "uid": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/uid",
                                        "type": "integer",
                                        "title": "The Uid Schema",
                                        "default": 0,
                                        "examples": [
                                            1
                                        ]
                                    },
                                    "utype": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/utype",
                                        "type": "string",
                                        "title": "The Utype Schema",
                                        "default": "",
                                        "examples": [
                                            "dispenser"
                                        ],
                                        "pattern": "^(.*)$" 
                                    },
                                    "uaddress": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/uaddress",
                                        "type": "string",
                                        "title": "The Uaddress Schema",
                                        "default": "",
                                        "examples": [
                                            "false"
                                        ],
                                        "pattern": "^(.*)$"
                                    },
                                    "unozzles": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/unozzles",
                                        "type": "boolean",
                                        "title": "The Unozzles Schema",
                                        "default": false,
                                        "examples": [
                                            false
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        "if": { 
            "properties": { "virtual": { "properties": { "entity": { "const" : "pde" } } } }
        },
        "then": {
            "properties": {
                "virtual": {
                    "properties": {
                        "nodes": {
                            "items": {
                                "required": [                                   
                                    "id",
                                    "type",
                                    "address",
                                    "nozzles"
                                ],
                                "properties": {
                                    "id": {                     
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/id",
                                            "type": "string",
                                            "title": "The Id Schema",
                                            "default": "",
                                            "examples": [
                                                "vrt_1"
                                            ],
                                        "pattern": "^(.*)$"
                                    },
                                    "type": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/type",
                                        "type": "string",
                                        "title": "The Type Schema",
                                        "default": "",
                                        "examples": [
                                            "dispenser"
                                        ],
                                        "pattern": "^(.*)$"
                                    },
                                    "address": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/address",
                                        "type": "integer",
                                        "title": "The Address Schema",
                                        "default": 0,
                                        "examples": [
                                            1
                                        ]
                                    },
                                    "nozzles": {
                                        "$id": "#/properties/virtual/items/properties/nodes/items/properties/nozzles",
                                        "type": "array",
                                        "title": "The Nozzles Schema",
                                        "items": {
                                            "$id": "#/properties/virtual/items/properties/nodes/items/properties/nozzles/items",
                                            "type": "integer",
                                            "title": "The Items Schema",
                                            "default": 0,
                                            "examples": [
                                                1,
                                                2,
                                                3
                                            ]
                                        }
                                    }
                                }
                            }                                           
                        }
                    }
                }
            }
        }
    }
  ]  
}

此JSON有效:

{
    "virtual": [
        {
            "type": "bus",
            "path": "VUS1",
            "entity": "pde",
            "nodes": [
                {
                    "id": "vrt_1",
                    "type": "string",
                    "address": 1,
                    "nozzles": [1, 2, 3]
                },
                {
                    "id": "vrt_2",
                    "type": "string",
                    "address": 2,
                    "nozzles": [1, 2, 3]
                }
            ]
        },
        {
            "type": "bus",
            "path": "VUS2",
            "entity": "topaz",
            "nodes": [          
                {
                    "uid": 1,
                    "utype": "string",
                    "uaddress": "false",
                    "unozzles": false
                },
                {
                    "uid": "vrt_1",
                    "utype": "string",
                    "uaddress": "false",
                    "unozzles": false
                }
            ]
        }
    ]
}

此JSON不应该应用,但被认为是有效的:

And this JSON should not be applied, but is considered valid:

{
    "virtual": [
        {
            "type": "bus",
            "path": "VUS1",
            "entity": "pde",
            "nodes": [
                {
                    "id_not_valid": "failure",
                    "type": 1,
                    "address": false,
                    "nozzles": [1, 2, 3]
                },
                {
                    "id": "vrt_2",
                    "type": "string",
                    "address": false,
                    "nozzles": [1, 2, 3]
                }
            ]
        },
        {
            "type": "bus",
            "path": "VUS2",
            "entity": "topaz",
            "nodes": [          
                {
                    "uid_not_valid": "failure",
                    "utype": 1,
                    "uaddress": "false",
                    "unozzles": false
                }
            ]
        }
    ]
}

理论上,不应验证第二个JSON.有几个原因:

In theory, the second JSON should not be validated. For several reasons:

  1. 对于entity ="pd",必填字段为"id","type","address"和"nozzles".在JSON的第二行中,字段"id"被字段"id_not_valid"替换->必填字段"id"不存在,验证必须以失败告终.相同的entity ="top"-"uid uid"替换为"id_not_valid"
  2. 对于entity ="pd",地址字段的类型为令牌,在第二行JSON中将其设置为false,这对应于类型"boolean",但是仍然会进行验证(如果您分配了数组或要处理的字符串值).对于entity ="top"类型,该类型为字符串,但是验证器还假定为其分配的整数值1是正确的字符串.

但是下面链接上的在线验证器说一切正常,并且两个JSON都符合该方案.

But the online validators on the links below say that everything is OK and both JSON conform to the scheme.

第一个站点

第二个站点

第三个网站

因此,我认为该方案中存在错误.
该方案本身是通过以下示例创建的: JSON模式编译示例

So I believe there is an error in the scheme.
The scheme itself was made by this example Example of JSON schema compilation

请提供任何有关修复JSON模式的评论和提示

Any comments and tips on fixing JSON-schema, please

推荐答案

架构 格式错误.

(我忽略了架构状态entity应该为"pde""topaz"的事实,但是实例具有"pd""top".我认为这是一个错字.)

(I'm ignoring the fact that the schema states entity should be "pde" or "topaz", but the instances have "pd" and "top". I assume this is a typo.)

anyOf内,您有两个项目,每个项目都有一个if条件关键字.该关键字表示的模式是

Inside the anyOf, you have two items, each with an if conditional keyword. The schema presented by this keyword is

{
  "properties": {
    "virtual": {
      "properties": {
        "entity": {
          "const": "topaz"
        }
      }
    }
  }
}

这是说如果 virtual具有entity属性,那么它应该是"topaz".但是properties的工作方式是,如果实例是对象,它只会通过验证失败.但是在#/properties中,您声明virtual应该是对象数组,其中每个项目包含entity属性.

This is saying that if virtual has an entity property, then it should be "topaz". But the way that properties works is that it only fails validation if the instance is an object. However in #/properties, you declare that virtual should be an an array of objects where each item contains an entity property.

由于virtual在您的实例中是一个数组,因此anyOf传递中没有任何if条件关键字,因此它们将这些子模式的else关键字视为不存在的(因此,默认通过).这导致anyOf通过的两个子方案.

Since virtual is an array in your instance, none of the if condition keywords in the anyOf pass, so they defer to the else keywords for those subschemas, which don't exist (so the pass by default). This results in both subschemas for the anyOf passing.

认为,您要做的是根据该项目的entity属性值验证数组中的每个项目.这意味着您可以在数组中同时包含一个pde项和一个topaz项.

I think what you're trying to do is validate each of the items inside the array based on the value of the entity property for that item. This means that you could have both a pde item and a topaz item in the array.

为此,您需要隔离差异所在的位置.在您的情况下,它是virtual数组中的项目级别.这是您需要放置anyOf的地方.

To do this you need to isolate where the variance is. In your case, it's the item level inside the virtual array. This is where you need to put your anyOf.

因此,您需要将anyOf添加到#/properties/virtual/items.这是架构中if/then构造可以键出entity属性并强制执行nodes属性的唯一点.

So you'll want to add your anyOf to #/properties/virtual/items. This is the only point in the schema where an if/then construct can key off of the entity property and enforce the nodes property.

编辑我会改变的事情

  1. 删除所有内部$id声明.它们仅重申文档中的位置,并且不提供其他功能.
  2. entity中删除typepattern声明.在这里enum就足够了,因为它声明值必须是数组中的一项.由于这些都是字符串,并且都匹配给定的模式,因此这些关键字是多余的.
  3. anyOf移到virtual内的properties关键字旁边,并将其更改为oneOf.这是最特定的位置,您可以在其中访问entities属性和nodes属性.将其更改为oneOf可确保完全正确.
  4. 删除if/then构造,并将常量值包含在then部分中.
  1. Remove all of the internal $id declarations. They only reiterate the location in the document and provide no additional functionality.
  2. Remove the type and pattern declarations from entity. enum is sufficient here because it declares that the values must be one of the items in the array. Since these are both strings and match the given pattern, those keywords are redundant.
  3. Move the anyOf alongside the properties keyword inside virtual and change it to a oneOf. This is the most specific location where you can access both the entities property and the nodes property. Changing it to a oneOf ensures that exactly one can be true.
  4. Drop the if/then construct and just include the constant value in the then portion.

最后,它的结构如下:

{
  ... ,
  "properties": {
    "virtual": {
      "type": "array",
      "title": "The Virtual Schema",
      "items": {
        "type": "object",
        "title": "The Items Schema",
        "required": [ "type", "path", "entity", "nodes" ],
        "properties": {
          "type": { ... },
          "path": { ... },
          "entity": {
            "title": "The Entity Schema",
            "default": "",
            "examples": [
              "topaz"
            ],
            "enum": ["pde", "topaz"]
          }
        },
        "oneOf": [
            {
                "properties": {
                    "entity": {"const": "topaz"},
                    "nodes": { ... }
                }
            },
            {
                "properties": {
                    "entity": {"const": "pde"},
                    "nodes": { ... }
                }
            }
        ]
      }
    }
  } 
}

在这里,我们声明virtual数组中的项目必须是需要4个属性的对象:typepathentitynodes.我们使用properties关键字显式定义typepathentity.但是我们有条件地使用oneOf定义nodes属性,并在每种情况下为entity属性指定一个常量值.

Here, we're declaring that the items within the virtual array must be objects requiring 4 properties: type, path, entity, and nodes. We explicitly define type, path, entity using the properties keyword. But we conditionally define the nodes property using the oneOf and specifying a constant value for the entity property in each case.

这篇关于JSON模式错误地成功验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆