JSON 可以包含具有不同键的项的数组的模式验证
JSON schema validation for array that can have items with different keys
我试图找到一个模式来验证具有多个项目的给定数组。这些项目可以有 2 个可能的键值。但是所有项目都应该与键具有相同的值。
如果 2 个可能的值是 'primary' 和 'secondary',那么所有键都应该是 'primary' 或者所有键都应该是 'secondary'。 oneOf 在这种情况下似乎不起作用。
有解决办法吗?任何帮助表示赞赏。谢谢。
架构:
{
type: "object",
properties: {
values: {
type: "array",
uniqueItems: true,
minItems: 1,
maxItems: 100,
items: {
anyOf: [
{ $ref: "#/definitions/primaryObj"} ,
{ $ref: "#/definitions/secondaryObj"}
]
}
},
},
definitions: {
primaryObj: {
type: "object",
required: ["id", "primary"],
properties: {
id: {
type: "string",
description: "The id",
},
primary: {
type: "string",
description: "primary value",
},
},
},
secondaryObj: {
type: "object",
required: ["id", "secondary"],
properties: {
id: {
type: "string",
description: "The id",
},
secondary: {
type: "string",
description: "secondary value",
},
},
},
},
required: ["values"],
}
示例输入 -
输入 1 - 应通过验证
{
"values": [
{
"id": "1",
"primary" : "hello"
},
{
"id": "2",
"primary" : "world"
}
]
}
输入 2 - 应通过验证
{
"values": [
{
"id": "1",
"secondary" : "hello"
},
{
"id": "2",
"secondary" : "world"
}
]
}
输入 3 - 验证失败
{
"values": [
{
"id": "1",
"primary" : "hello"
},
{
"id": "2",
"secondary" : "world"
}
]
}
你离这里很近。您需要进行两项更改才能获得所需的验证。 (我假设您使用的是 draft-07,尽管这也适用于较新的草稿)
首先,让我们来看看最上面的部分。
anyOf
关键字指定如下:
An instance validates successfully against this keyword if it
validates successfully against at least one schema defined by this
keyword's value.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.7.2
您只希望引用的子模式之一为真!
oneOf
定义类似:
An instance validates successfully against this keyword if it
validates successfully against exactly one schema defined by this
keyword's value.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.7.3
因此我们更改您的架构以检查是否只有一个引用有效...
"items": {
"oneOf": [
{
"$ref": "#/definitions/primaryObj"
},
{
"$ref": "#/definitions/secondaryObj"
}
]
}
但这仍然是不正确的。让我们刷新一下 items
的作用。
This keyword determines how child instances validate for arrays,
and does not directly validate the immediate instance itself.
If "items" is a schema, validation succeeds if all elements in the
array successfully validate against that schema.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.4.1
看起来我们做对了,但是上面引用的第一段试图传达 items
将其子模式值应用于数组中的每个项目,而不是“作为整个数组”。
我们上面的子模式正在做的是单独检查数组中的每个项目,与其他项目隔离,它们是您定义的“主要”或“次要”。
我们想要做的是检查数组中的所有项目是“主要”还是“次要”。为此,我们需要将 oneOf
移到 items
.
之外
"oneOf": [
{
"items": {
"$ref": "#/definitions/primaryObj"
}
},
{
"items": {
"$ref": "#/definitions/secondaryObj"
}
}
]
快到了!这几乎可行,但我们仍然发现混合主要和次要不会导致验证失败。
让我们检查一下我们的假设。我们假设当实例数据在数组中的对象中有 primary
和 secondary
时验证应该失败。我们可以通过将 oneOf
中的一个子模式更改为 false 来测试这一点,强制检查第一个子模式定义(主要)。它应该检查数组中的所有项目都是主要的,任何次要的都应该导致验证失败。
我们必须记住,JSON 架构是基于约束的。任何不受约束的东西都是允许的。
如果我们查看 primaryObj
的定义,它需要并定义 id
和 primary, but this doesn't inherintly prevent additioanl keys in the object. To do that, we need to add
"additionalProperties": false`(对于两个定义)的验证。
最终结果如下所示。您可以在 https://jsonschema.dev/s/3ZKBp
查看现场演示
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"values": {
"type": "array",
"uniqueItems": true,
"minItems": 1,
"maxItems": 100,
"oneOf": [
{
"items": {
"$ref": "#/definitions/primaryObj"
}
},
{
"items": {
"$ref": "#/definitions/secondaryObj"
}
}
]
}
},
"definitions": {
"primaryObj": {
"type": "object",
"required": [
"id",
"primary"
],
"properties": {
"id": {
"type": "string",
"description": "The id"
},
"primary": {
"type": "string",
"description": "primary value"
}
},
"additionalProperties": false
},
"secondaryObj": {
"type": "object",
"required": [
"id",
"secondary"
],
"properties": {
"id": {
"type": "string",
"description": "The id"
},
"secondary": {
"type": "string",
"description": "secondary value"
}
},
"additionalProperties": false
}
},
"required": [
"values"
]
}
我试图找到一个模式来验证具有多个项目的给定数组。这些项目可以有 2 个可能的键值。但是所有项目都应该与键具有相同的值。
如果 2 个可能的值是 'primary' 和 'secondary',那么所有键都应该是 'primary' 或者所有键都应该是 'secondary'。 oneOf 在这种情况下似乎不起作用。
有解决办法吗?任何帮助表示赞赏。谢谢。
架构:
{
type: "object",
properties: {
values: {
type: "array",
uniqueItems: true,
minItems: 1,
maxItems: 100,
items: {
anyOf: [
{ $ref: "#/definitions/primaryObj"} ,
{ $ref: "#/definitions/secondaryObj"}
]
}
},
},
definitions: {
primaryObj: {
type: "object",
required: ["id", "primary"],
properties: {
id: {
type: "string",
description: "The id",
},
primary: {
type: "string",
description: "primary value",
},
},
},
secondaryObj: {
type: "object",
required: ["id", "secondary"],
properties: {
id: {
type: "string",
description: "The id",
},
secondary: {
type: "string",
description: "secondary value",
},
},
},
},
required: ["values"],
}
示例输入 -
输入 1 - 应通过验证
{
"values": [
{
"id": "1",
"primary" : "hello"
},
{
"id": "2",
"primary" : "world"
}
]
}
输入 2 - 应通过验证
{
"values": [
{
"id": "1",
"secondary" : "hello"
},
{
"id": "2",
"secondary" : "world"
}
]
}
输入 3 - 验证失败
{
"values": [
{
"id": "1",
"primary" : "hello"
},
{
"id": "2",
"secondary" : "world"
}
]
}
你离这里很近。您需要进行两项更改才能获得所需的验证。 (我假设您使用的是 draft-07,尽管这也适用于较新的草稿)
首先,让我们来看看最上面的部分。
anyOf
关键字指定如下:
An instance validates successfully against this keyword if it
validates successfully against at least one schema defined by this
keyword's value.https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.7.2
您只希望引用的子模式之一为真!
oneOf
定义类似:
An instance validates successfully against this keyword if it
validates successfully against exactly one schema defined by this
keyword's value.https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.7.3
因此我们更改您的架构以检查是否只有一个引用有效...
"items": {
"oneOf": [
{
"$ref": "#/definitions/primaryObj"
},
{
"$ref": "#/definitions/secondaryObj"
}
]
}
但这仍然是不正确的。让我们刷新一下 items
的作用。
This keyword determines how child instances validate for arrays, and does not directly validate the immediate instance itself.
If "items" is a schema, validation succeeds if all elements in the array successfully validate against that schema.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.4.1
看起来我们做对了,但是上面引用的第一段试图传达 items
将其子模式值应用于数组中的每个项目,而不是“作为整个数组”。
我们上面的子模式正在做的是单独检查数组中的每个项目,与其他项目隔离,它们是您定义的“主要”或“次要”。
我们想要做的是检查数组中的所有项目是“主要”还是“次要”。为此,我们需要将 oneOf
移到 items
.
"oneOf": [
{
"items": {
"$ref": "#/definitions/primaryObj"
}
},
{
"items": {
"$ref": "#/definitions/secondaryObj"
}
}
]
快到了!这几乎可行,但我们仍然发现混合主要和次要不会导致验证失败。
让我们检查一下我们的假设。我们假设当实例数据在数组中的对象中有 primary
和 secondary
时验证应该失败。我们可以通过将 oneOf
中的一个子模式更改为 false 来测试这一点,强制检查第一个子模式定义(主要)。它应该检查数组中的所有项目都是主要的,任何次要的都应该导致验证失败。
我们必须记住,JSON 架构是基于约束的。任何不受约束的东西都是允许的。
如果我们查看 primaryObj
的定义,它需要并定义 id
和 primary, but this doesn't inherintly prevent additioanl keys in the object. To do that, we need to add
"additionalProperties": false`(对于两个定义)的验证。
最终结果如下所示。您可以在 https://jsonschema.dev/s/3ZKBp
查看现场演示{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"values": {
"type": "array",
"uniqueItems": true,
"minItems": 1,
"maxItems": 100,
"oneOf": [
{
"items": {
"$ref": "#/definitions/primaryObj"
}
},
{
"items": {
"$ref": "#/definitions/secondaryObj"
}
}
]
}
},
"definitions": {
"primaryObj": {
"type": "object",
"required": [
"id",
"primary"
],
"properties": {
"id": {
"type": "string",
"description": "The id"
},
"primary": {
"type": "string",
"description": "primary value"
}
},
"additionalProperties": false
},
"secondaryObj": {
"type": "object",
"required": [
"id",
"secondary"
],
"properties": {
"id": {
"type": "string",
"description": "The id"
},
"secondary": {
"type": "string",
"description": "secondary value"
}
},
"additionalProperties": false
}
},
"required": [
"values"
]
}