jsonschema 属性验证需要 and/or 有条件地需要

jsonschema validation of properties required and/or conditionally required

我需要验证始终具有 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" 
}

不幸的是,这个 的出色答案部分涵盖了我的情况,但是我没有设法构建适合我的 json 架构。

编辑:

这是我试过的。

{
    "$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 模式是一个约束系统,其中每个子模式的约束是单独评估的。这意味着 "additionalProperties" 只能 "see" 同一直接模式对象中的 "properties" 或 "patternProperties"。

此外,它不能 "see" 基于 "required" 的属性,只能基于 "properties" 和 "patternProperties"。

据我所知,如果您在 anyOf 的 each 分支中设置 "additionalProperties": false,则 none 应该可以作为唯一允许的 属性 是 "type"。如果您这样做并且它允许 "type" 以外的属性,那么我想知道您使用的是什么实现。

以下模式适用于您的示例。希望这对其他人有帮助。诀窍是使用 additionalPropertiesmaxProperties 的组合,在正确的位置使用 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
}