如何禁止 json 模式数组中的某些任意项多次出现

How to forbid certain anyOf items in json schema array to occur more than once

考虑以下 json 架构:

{
    "type": "array",
    "items": {
        "anyOf":[
            { 
                "type": "object",
                "additionalProperties":false,
                "properties": {
                    "foo":{"type":"string"}
                }
            },
            {
                "type": "object",
                "additionalProperties":false,
                "properties": {
                    "bar":{"type":"number"}
                }
            }
        ]
    }
}

我如何指定 anyOf 中的第一个模式可能会无限期出现,但第二个模式可能只出现一次?

下面的 json 应该是 有效的 因为它只包含一个匹配第二个 anyOf 模式的元素:

[
  {
    "foo":"hello"
  },
  {
    "foo":"world"
  },
  {
    "bar":42
  }
]

下面的 json 应该是 无效的 因为它包含多个与第二个 anyOf 架构匹配的元素:

[
  {
    "foo":"hello"
  },
  {
    "foo":"world"
  },
  {
    "bar":42
  },
  {
    "bar":24
  }
]

我正在寻找任何 json-schema 草稿版本的解决方案。

在 2019-09 和 2020-12 草案中,您可以使用 contains + minContains + maxContains 来断言某些东西最多可以出现在数组中一次。

{
  "type": "array",
  "items": {
    "anyOf": [
      { "$ref": "#/$defs/foo-string" },
      { "$ref": "#/$defs/foo-number" }
    ]
  },
  "contains": { "$ref": "#/$defs/foo-string" },
  "minContains": 0,
  "maxContains": 1
}

在 draft-04 - draft-07 中,无法表达 contains-only-one。你能做的最好的事情就是要求只能出现一次的东西总是数组的第一项。这表示第一项可以是“foo-string”或“foo-number”,其余所有项都必须是“foo-number”。

{
  "type": "array",
  "items": [
    {
      "anyOf": [
        { "$ref": "#/$defs/foo-string" },
        { "$ref": "#/$defs/foo-number" }
      ]
    }
  ],
  "additionalItems": { "$ref": "#/definitions/foo-number" }
}