JSON 架构需要特定的数组元素

JSON Schema require a specific array element

我将属性列表定义为 json 模式:

{
  "$schema": "http://json-schema.org/schema#",
  "type": "object",


  "definitions": {

    "attribute": {
      "type": "object",
      "properties": {
        "symbolic-name": { "type":"string"},
        "value": { "type":"string"}
      },
      "required": ["symbolic-name", "value"]
    },

    "displayname": {
      "type": "object",
      "properties": {
        "symbolic-name": {"enum":["displayName"]},
        "value": { "type":"string"}
      },
      "required": ["symbolic-name", "value"]
    }

  },

  "properties": {
    "attributes":{
      "type": "array",
      // This is the crucial point:
      "items": {"oneOf": [
               {"$ref": "#/definitions/attribute"},
               {"$ref": "#/definitions/displayname"}
      ]},
      "uniqueItems": true
    }
  }
}

我想要求列表只有一个属性 symbolic-name="displayName"

一个有效的数据对象应该是:

{
  "attributes":[
    {"symbolic-name": "displayName", "value": "Display Name"},
    {"symbolic-name": "somethingElse", "value": "value1"}
    {"symbolic-name": "somethingElse", "value": "value2"}
  ]
}

现在,这无法验证,因为 displayName 属性不仅匹配 "oneOf",而且还匹配两个限制。我无法将其更改为 "allOf",因为那样除 displayName 之外的所有其他属性都将不再匹配。

为了使您的 "oneOf" 正常工作,您的 "attribute" 和 "displayname" 架构需要相互排斥 - 如所写,任何有效的 "displayname"也是有效的 "attribute"。我们可以通过排除 "displayName" 作为 "attribute":

的有效符号名称来做到这一点
"symbolic-name": {
    "type": "string",
    "not": {"enum": ["displayName"]}
}

现在符号名称为 "displayName" 的元素可以匹配 "displayname" 定义,但永远不会匹配 "attribute" 定义。

你问题的另一部分是关于在你的数组中恰好有一个 "displayname"。这更棘手。它还取决于您使用的 JSON Schema 的草稿。 4 和 6 已实施,7 于周一发布 - 仅声明 "$schema": "http://json-schema.org/schema#" 意味着您使用的是最新的,即 7。我建议使用 $schema 的特定草案而不是非-第一个可能会更改,恕不另行通知。

如果您同意 "displayname" 是数组的 first 元素,那么这在任何草稿中都有效(而且您甚至不需要 "oneOf"):

"items": [{"$ref": "#/definitions/displayname"}],
"additionalItems": {"$ref": "#/definitions/attribute"}

注意这里的"items"是一个数组。这意味着第一项必须是 "displayname" 并且超出第一项的所有其他项目必须是 "attribute"s.

如果您想在任何位置允许 "displayname",那就更难了。从 draft-06 开始,有 "contains",它至少需要一项来匹配给定的模式。但是没有简单的方法可以说"at most one item"。然而,"minContains""maxContains" 已被建议用于 draft-08:https://github.com/json-schema-org/json-schema-spec/issues/441

现在,希望您可以接受 "displayname" 要求第一个位置,因为这在所有草稿中都适用。