我正在使用 JSON.Net 架构验证包,遇到了一个非常奇怪的问题。我已经将该问题追踪到在下面的anyObject
定义中使用anyOf
:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/example/1.0/schema.json",
"anyOf": [
{
"$ref": "#/definitions/anyObject"
}
],
"definitions": {
"anyObject": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
},
"required": [
"type"
],
"anyOf": [
{
"if": {
"properties": {
"type": {
"const": "typeA"
}
}
},
"then": {
"$ref": "#/definitions/typeA"
},
"else": false
},
{
"if": {
"properties": {
"type": {
"const": "typeB"
}
}
},
"then": {
"$ref": "#/definitions/typeB"
},
"else": false
}
]
},
"bodyDefinition": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"type": "string"
}
},
"required": [
"$computed"
]
},
"then": {
"$ref": "#/definitions/computedBody"
},
"else": {
"$ref": "#/definitions/wildcardBody"
}
},
{
"type": "string"
}
]
},
"wildcardBody": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/bodyDefinition"
}
},
"firstComputedValue": {
"type": "object",
"additionalProperties": false,
"properties": {
"$computed": {
"const": "first"
},
"values": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/bodyDefinition"
}
}
},
"required": [
"$computed",
"values"
]
},
"computedBody": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"const": "first"
}
}
},
"then": {
"$ref": "#/definitions/firstComputedValue"
},
"else": false
}
]
},
"typeA": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeA"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
},
"typeB": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeB"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
}
}
}
当我测试这个 json 时:
{
"type": "typeB",
"body":{
"$computed":"first",
"values":[]
}
}
它应该被标记为无效,因为values
至少需要一个值。但是它是有效的。以下 JSON 应被视为有效,并且上述架构确实正确断言:
{
"type": "typeB",
"body":{
"$computed":"first",
"values":["foo"]
}
}
如果我从anyObject
定义中删除typeA
,则验证将正确执行。下面是正确验证的架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/schemas/example/1.0/schema.json",
"anyOf": [
{
"$ref": "#/definitions/anyObject"
}
],
"definitions": {
"anyObject": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
},
"required": [
"type"
],
"anyOf": [
{
"if": {
"properties": {
"type": {
"const": "typeB"
}
}
},
"then": {
"$ref": "#/definitions/typeB"
},
"else": false
}
]
},
"bodyDefinition": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"type": "string"
}
},
"required": [
"$computed"
]
},
"then": {
"$ref": "#/definitions/computedBody"
},
"else": {
"$ref": "#/definitions/wildcardBody"
}
},
{
"type": "string"
}
]
},
"wildcardBody": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/bodyDefinition"
}
},
"firstComputedValue": {
"type": "object",
"additionalProperties": false,
"properties": {
"$computed": {
"const": "first"
},
"values": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/bodyDefinition"
}
}
},
"required": [
"$computed",
"values"
]
},
"computedBody": {
"oneOf": [
{
"if": {
"properties": {
"$computed": {
"const": "first"
}
}
},
"then": {
"$ref": "#/definitions/firstComputedValue"
},
"else": false
}
]
},
"typeA": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeA"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
},
"typeB": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"const": "typeB"
},
"body": {
"$ref": "#/definitions/bodyDefinition"
}
},
"required": [
"type"
]
}
}
}
任何人都可以查看此定义是否存在问题,或者这是 JSON.Net 架构包的问题?
此测试是针对架构验证器的在线版本完成的 https://www.jsonschemavalidator.net/
我认为这是一个错误。我会和图书馆的作者谈谈!
为了调试,我遵循了整个架构的验证过程,将$ref
或then
或else
设置为false
...当我到达computedBody
时,我将其更改为以下内容...
"computedBody": {
"if": {
"properties": {
"$computed": {
"const": "first"
}
}
},
"then": false,
"else": false
}
验证仍然返回正值,这应该是不可能的。我通过将子架构设置为 false
并看到验证返回负面结果来证明它达到了computedBody
。
(不需要包装computedBody
子架构的oneOf
。 if
在架构级别有效即可(。