我需要验证一个始终具有 2 个属性的 json 对象:
类型可以是“A”、“B”或“C”,
当类型为“A”时,属性“foo”也是必需的,并且不允许附加属性。
好的:
{
"type": "A",
"name": "a",
"foo": "a",
}
不好:
{
"type": "A",
"name": "a",
"foo": "a",
"lol": "a"
}
当类型为“B”时,需要属性“bar”,不允许附加属性。
当类型为“C”时,属性“bar”是必需的,并且可选地还可以存在“zen”属性。
好的:
{
"type": "C",
"name": "a",
"bar": "a",
"zen": "a"
}
{
"type": "C",
"name": "a",
"bar": "a",
}
不好:
{
"type": "C",
"name": "a",
"bar": "a",
"lol": "a"
}
不幸的是,这个问题的出色答案部分涵盖了我的情况,但是我没有设法构建适合我的jsonschema。
编辑:
这是我尝试过的。
{
"$schema": "http://json-schema.org/draft-04/schema",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["A", "B", "C"]
},
"name": {"type": "string"},
"foo": {"type": "string"},
"bar": {"type": "string"},
"zen": {"type": "string"},
},
"anyOf": [
{
"properties": {"type": {"enum": ["A"]}},
"required": ["foo"],
},
{
"properties": {"type": {"enum": ["B"]}},
"required": ["bar"],
},
{
"properties": {"type": {"enum": ["C"]}},
"required": ["bar"],
},
]
}
我的问题是,在“anyOf”中的对象内将“additionalProperties”字段设置为 false 不会给我预期的结果。
例如以下 json 通过了验证,尽管它具有附加属性“lol”
{
"type": "A",
"name": "a",
"foo": "a",
"lol": "a"
}
JSON Schema 是一个约束系统,其中每个子模式的约束都是单独评估的。这意味着“additionalProperties”只能“看到”同一直接模式对象中的“properties”或“patternProperties”。
此外,它无法“查看”基于“required”的属性,只能基于“properties”和“patternProperties”。
据我所知,如果您在 anyOf 的 each 分支中设置 "additionalProperties": false ,则这些都不起作用,因为唯一允许的属性是“type”。如果您这样做了并且它允许除“类型”之外的属性,那么我想知道您正在使用什么实现。
以下模式在您的示例中对我有用。希望这对其他人有帮助。技巧是使用
additionalProperties
和 maxProperties
的组合,并在正确的位置使用 required
:
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"A",
"B",
"C"
]
},
"name": {
"type": "string"
},
"foo": {
"type": "string"
},
"bar": {
"type": "string"
},
"zen": {
"type": "string"
}
},
"required": [
"name",
"type"
],
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "A"
}
}
},
"then": {
"required": [
"foo"
],
"maxProperties": 3
}
},
{
"if": {
"properties": {
"type": {
"const": "B"
}
}
},
"then": {
"required": [
"bar"
],
"maxProperties": 3
}
},
{
"if": {
"properties": {
"type": {
"const": "C"
}
}
},
"then": {
"required": [
"bar"
],
"maxProperties": 4
}
}
],
"additionalProperties": false
}
在开发我的游戏《Bolero: The Lost Isle》时,我想要一种好方法来验证我需要制作的所有数据,但我的游戏中的许多对象都具有继承结构。然后我开始学习 JSON Schema 作为一个潜在的解决方案。我一直在 Hackolade 中编辑我的模式,但是您可以通过查看我制作的模型图之一来了解要点(顺便说一句,硬线与虚线轮廓传达了必需的 true 与必需的 false,不包括子模式)。
此处唯一将“additionalProperties”设置为“true”的对象是与 oneOf 分割位于同一层上的“数据”。子模式(以及子模式)内的“数据”将“additionalProperties”设置为“false”,这会覆盖“true”。 “类型”字符串的工作方式与您的解决方案类似,它们每个都有设置为与子模式标题相同的常量值。
我已经在 Visual Studio Code 中实现了此架构,并且验证和自动完成功能非常棒!