JSON模式错误地成功验证 [英] Erroneous successful validation by JSON-schema
问题描述
节点中的字段取决于实体的值.也就是说,如果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:
- 对于entity ="pd",必填字段为"id","type","address"和"nozzles".在JSON的第二行中,字段"id"被字段"id_not_valid"替换->必填字段"id"不存在,验证必须以失败告终.相同的entity ="top"-"uid uid"替换为"id_not_valid"
- 对于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.
编辑我会改变的事情
- 删除所有内部
$id
声明.它们仅重申文档中的位置,并且不提供其他功能. - 从
entity
中删除type
和pattern
声明.在这里enum
就足够了,因为它声明值必须是数组中的一项.由于这些都是字符串,并且都匹配给定的模式,因此这些关键字是多余的. - 将
anyOf
移到virtual
内的properties
关键字旁边,并将其更改为oneOf
.这是最特定的位置,您可以在其中访问entities
属性和nodes
属性.将其更改为oneOf
可确保完全正确. - 删除
if
/then
构造,并将常量值包含在then
部分中.
- Remove all of the internal
$id
declarations. They only reiterate the location in the document and provide no additional functionality. - Remove the
type
andpattern
declarations fromentity
.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. - Move the
anyOf
alongside theproperties
keyword insidevirtual
and change it to aoneOf
. This is the most specific location where you can access both theentities
property and thenodes
property. Changing it to aoneOf
ensures that exactly one can be true. - Drop the
if
/then
construct and just include the constant value in thethen
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个属性的对象:type
,path
,entity
和nodes
.我们使用properties
关键字显式定义type
,path
,entity
.但是我们有条件地使用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屋!