如何定义 JSON 模式,其中对象数组至少包含具有预期名称的元素
How to define a JSON schema where an array of objects contains at least the elements with the expected names
我想定义一个 JSON 模式(草案 04),其中对象数组(此处 files
)包含 至少 具有定义的 name
s(此处为 a
、b
、c
)。
- 这应该通过:
"files": [
{ "name": "a" },
{ "name": "b" },
{ "name": "c" }
]
- 这应该失败(缺少名称为
c
的元素):
"files": [
{ "name": "a" },
{ "name": "b" }
]
- 这应该失败(缺少名称为
c
的元素):
"files": [
{ "name": "a" },
{ "name": "b" },
{ "name": "a" }
]
- 这应该通过:
"files": [
{ "name": "a" },
{ "name": "b" },
{ "name": "c" },
{ "name": "d" }
]
minItems
、uniqueItems
和 enum
允许我涵盖案例 1、2 和 3,但它不涵盖案例 4,因为它不允许名称 d
:
"files": {
"minItems": 3,
"uniqueItems": true,
"items": {
"properties": {
"name": {
"enum": ["a", "b", "c"]
}
}
}
}
编写验证以至少需要名称为 a
、b
和 c
的元素的任何想法,同时还允许 JSON 中具有其他名称的其他项目架构草案 04?
我们先用一些draft-06或更高版本的关键字来看,因为它更容易理解。然后我们将其翻译为 draft-04。
我们可以使用 contains
关键字来断言数组至少包含一个与架构匹配的项目。此示例显示断言数组必须包含具有 属性 “名称”且值为 "a"
.
的对象
{
"contains": {
"type": "object",
"properties": {
"name": { "const": "a" }
},
"required": ["name"]
}
}
您可以像这样使用 allOf
组合多个断言来断言“b”和“c”。
{
"allOf": [
{ "$ref": "#/definitions/contains-a" },
{ "$ref": "#/definitions/contains-b" },
{ "$ref": "#/definitions/contains-c" }
]
}
现在我们需要翻译成 draft-04。 const
很简单。
{ "const": "a" }
变成
{ "enum": ["a"] }
contains
的转换远没有那么直观,但它确实有效。我建议将它们放在 definitions
中(如 allOf
示例中所示)以使您的模式更具可读性。
{ "contains": { "$ref": "#/definitions/name-a" } }
变成
{
"not": {
"items": {
"not": { "$ref": "#/definitions/name-a" }
}
}
}
完整(详细)解决方案:
"files": {
"not": {
"items": {
"not": {
"type": "object",
"properties": {
"name": { "enum": ["a"] }
},
"required": ["name"]
},
"not": {
"type": "object",
"properties": {
"name": { "enum": ["b"] }
},
"required": ["name"]
},
"not": {
"type": "object",
"properties": {
"name": { "enum": ["c"] }
},
"required": ["name"]
}
}
}
}
我想定义一个 JSON 模式(草案 04),其中对象数组(此处 files
)包含 至少 具有定义的 name
s(此处为 a
、b
、c
)。
- 这应该通过:
"files": [
{ "name": "a" },
{ "name": "b" },
{ "name": "c" }
]
- 这应该失败(缺少名称为
c
的元素):
"files": [
{ "name": "a" },
{ "name": "b" }
]
- 这应该失败(缺少名称为
c
的元素):
"files": [
{ "name": "a" },
{ "name": "b" },
{ "name": "a" }
]
- 这应该通过:
"files": [
{ "name": "a" },
{ "name": "b" },
{ "name": "c" },
{ "name": "d" }
]
minItems
、uniqueItems
和 enum
允许我涵盖案例 1、2 和 3,但它不涵盖案例 4,因为它不允许名称 d
:
"files": {
"minItems": 3,
"uniqueItems": true,
"items": {
"properties": {
"name": {
"enum": ["a", "b", "c"]
}
}
}
}
编写验证以至少需要名称为 a
、b
和 c
的元素的任何想法,同时还允许 JSON 中具有其他名称的其他项目架构草案 04?
我们先用一些draft-06或更高版本的关键字来看,因为它更容易理解。然后我们将其翻译为 draft-04。
我们可以使用 contains
关键字来断言数组至少包含一个与架构匹配的项目。此示例显示断言数组必须包含具有 属性 “名称”且值为 "a"
.
{
"contains": {
"type": "object",
"properties": {
"name": { "const": "a" }
},
"required": ["name"]
}
}
您可以像这样使用 allOf
组合多个断言来断言“b”和“c”。
{
"allOf": [
{ "$ref": "#/definitions/contains-a" },
{ "$ref": "#/definitions/contains-b" },
{ "$ref": "#/definitions/contains-c" }
]
}
现在我们需要翻译成 draft-04。 const
很简单。
{ "const": "a" }
变成
{ "enum": ["a"] }
contains
的转换远没有那么直观,但它确实有效。我建议将它们放在 definitions
中(如 allOf
示例中所示)以使您的模式更具可读性。
{ "contains": { "$ref": "#/definitions/name-a" } }
变成
{
"not": {
"items": {
"not": { "$ref": "#/definitions/name-a" }
}
}
}
完整(详细)解决方案:
"files": {
"not": {
"items": {
"not": {
"type": "object",
"properties": {
"name": { "enum": ["a"] }
},
"required": ["name"]
},
"not": {
"type": "object",
"properties": {
"name": { "enum": ["b"] }
},
"required": ["name"]
},
"not": {
"type": "object",
"properties": {
"name": { "enum": ["c"] }
},
"required": ["name"]
}
}
}
}