JSON 架构 - 数组/列表验证可以与 anyOf 结合使用吗?
JSON Schema - can array / list validation be combined with anyOf?
我有一份 json 文件,我正尝试使用此表单验证:
...
"products": [{
"prop1": "foo",
"prop2": "bar"
}, {
"prop3": "hello",
"prop4": "world"
},
...
一个对象可能有多种不同的形式。我的架构如下所示:
...
"definitions": {
"products": {
"type": "array",
"items": { "$ref": "#/definitions/Product" },
"Product": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/Product_Type1" },
{ "$ref": "#/definitions/Product_Type2" },
...
]
},
"Product_Type1": {
"type": "object",
"properties": {
"prop1": { "type": "string" },
"prop2": { "type": "string" }
},
"Product_Type2": {
"type": "object",
"properties": {
"prop3": { "type": "string" },
"prop4": { "type": "string" }
}
...
除此之外,个别产品数组对象的某些属性可能会通过进一步使用 anyOf
或 oneOf
.
来间接定向
我 运行 使用内置模式验证 VSCode 中的问题,它会为 products
数组中不匹配 [=] 的每个项目抛出错误16=].
因此,验证器似乎锁定了它找到的第一个 oneOf
,并且不会针对任何其他类型进行验证。
我没有发现 jsonschema.org 上的 oneOf
机制有任何限制。并且这里没有提到它在专门处理数组的页面中使用:https://json-schema.org/understanding-json-schema/reference/array.html
我的尝试可行吗?
您的一般方法没问题。让我们举一个稍微简单的例子来说明问题所在。
鉴于此架构
{
"oneOf": [
{ "properties": { "foo": { "type": "integer" } } },
{ "properties": { "bar": { "type": "integer" } } }
]
}
而这个实例
{ "foo": 42 }
乍一看,这似乎匹配 /oneOf/0
而不是 oneOf/1
。它实际上匹配两个模式,这违反了 oneOf
施加的唯一约束,并且 oneOf
失败。
请记住,JSON 架构中的每个关键字都是一个约束。任何未被架构明确排除的内容都是允许的。 /oneOf/1
模式中没有任何内容表明 "foo" 属性 是不允许的。也没有说 "foo" 是必需的。它只是说如果实例有一个关键字"foo",那么它必须是一个整数。
要解决此问题,您需要 required
,根据情况可能需要 additionalProperties
。我在这里展示了您将如何使用 additionalProperties
,但我建议您不要使用它,除非您需要,因为它确实有一些有问题的属性。
{
"oneOf": [
{
"properties": { "foo": { "type": "integer" } },
"required": ["foo"],
"additionalProperties": false
},
{
"properties": { "bar": { "type": "integer" } },
"required": ["bar"],
"additionalProperties": false
}
]
}
我有一份 json 文件,我正尝试使用此表单验证:
...
"products": [{
"prop1": "foo",
"prop2": "bar"
}, {
"prop3": "hello",
"prop4": "world"
},
...
一个对象可能有多种不同的形式。我的架构如下所示:
...
"definitions": {
"products": {
"type": "array",
"items": { "$ref": "#/definitions/Product" },
"Product": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/Product_Type1" },
{ "$ref": "#/definitions/Product_Type2" },
...
]
},
"Product_Type1": {
"type": "object",
"properties": {
"prop1": { "type": "string" },
"prop2": { "type": "string" }
},
"Product_Type2": {
"type": "object",
"properties": {
"prop3": { "type": "string" },
"prop4": { "type": "string" }
}
...
除此之外,个别产品数组对象的某些属性可能会通过进一步使用 anyOf
或 oneOf
.
我 运行 使用内置模式验证 VSCode 中的问题,它会为 products
数组中不匹配 [=] 的每个项目抛出错误16=].
因此,验证器似乎锁定了它找到的第一个 oneOf
,并且不会针对任何其他类型进行验证。
我没有发现 jsonschema.org 上的 oneOf
机制有任何限制。并且这里没有提到它在专门处理数组的页面中使用:https://json-schema.org/understanding-json-schema/reference/array.html
我的尝试可行吗?
您的一般方法没问题。让我们举一个稍微简单的例子来说明问题所在。
鉴于此架构
{
"oneOf": [
{ "properties": { "foo": { "type": "integer" } } },
{ "properties": { "bar": { "type": "integer" } } }
]
}
而这个实例
{ "foo": 42 }
乍一看,这似乎匹配 /oneOf/0
而不是 oneOf/1
。它实际上匹配两个模式,这违反了 oneOf
施加的唯一约束,并且 oneOf
失败。
请记住,JSON 架构中的每个关键字都是一个约束。任何未被架构明确排除的内容都是允许的。 /oneOf/1
模式中没有任何内容表明 "foo" 属性 是不允许的。也没有说 "foo" 是必需的。它只是说如果实例有一个关键字"foo",那么它必须是一个整数。
要解决此问题,您需要 required
,根据情况可能需要 additionalProperties
。我在这里展示了您将如何使用 additionalProperties
,但我建议您不要使用它,除非您需要,因为它确实有一些有问题的属性。
{
"oneOf": [
{
"properties": { "foo": { "type": "integer" } },
"required": ["foo"],
"additionalProperties": false
},
{
"properties": { "bar": { "type": "integer" } },
"required": ["bar"],
"additionalProperties": false
}
]
}