16

大家好,提前感谢。

我正在尝试创建一个 JSON 模式来强制一个数组包含一个 A 和 B 对象以及 NC 对象,其中 A 和 B 是 C 对象,N 是一个整数,包含在 0 和无穷大之间。

为此:

[A, B] [A, B, C1] [A, B, C1, .., CN]

都是有效的,虽然:

[A] [A, C1] [A, C1, .., CN]

无效。_

为了清楚起见,A 和 B 必须在场。C 对象是可选的,尽管您可以拥有任意数量的对象。

C 对象模式:


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "C Object",

  "type": "object",
  "required": ["id", "name"],

  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    }
  },
  "additionalProperties": false
}

因此,C 对象是任何仅包含属性“id”和“name”的有效 JSON 对象,其中“id”是整数,“name”是字符串。

A 和 B 对象模式:


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "A Object",

  "type": "object",
  "required": ["id", "name"],

  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string",
      "enum": ["A"]
    }
  },
  "additionalProperties": false
}

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "B Object",

  "type": "object",
  "required": ["id", "name"],

  "properties": {
    "id": {
      "type": "integer"
    },
    "name": {
      "type": "string",
      "enum": ["B"]
    }
  },
  "additionalProperties": false
}

A 和 B 对象与 C 对象的不同之处在于强制执行名称值。A 对象的名称值必须是包含在字段 enum 中的值,其中 enum 包含单个值。

我迄今为止最完整的架构是:


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "To Date Solution",
  "description": "So far this is the most complete attempt at enforcing values to be contained within a JSON structure using JSON schemas.",

  "type": "array"
  "items": {
    "allOf": [
      {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "title": "C Object",

        "type": "object",
        "required": ["id", "name"],

        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          }
        },
        "additionalProperties": false
      }
    ]
  }
}

这强制其中包含的所有对象必须是 C 类型,A 和 B 是,尽管我不确定如何强制至少 A 和 B 的单个实例包含在我的数组中。

4

2 回答 2

13

您正在寻找的内容称为“元组输入”。

如果items关键字的值是一个数组,那么数组数据中的项必须与对应位置的模式匹配。其他项目(最后一个索引之后)匹配additionalItems(如果additionalItemsis则不允许false)。

所以,大致你想要的是这样的:

{
    "type": "array",
    "items": [
        {"$ref": "#/definitions/itemTypeA"},
        {"$ref": "#/definitions/itemTypeB"}
    ],
    "additionalItems": {"$ref": "#/definitions/itemTypeC"},
    "definitions": {
        ... actual definitions for A/B/C ...
    }
}

如果要确保A 和 B 存在,则只需使用 指定最小长度minItems,因此至少有两个项目(由于“元组类型”,必须与 A 和 B 匹配)。

(这也假设 A 和 B 是数组中的第一项。如果这不是您想要的,那么它会变得更复杂一些 - 尽管contains为 v5 提出了一个关键字可以巧妙地处理这个问题。)

更详细的现场演示:

于 2013-11-06T18:00:27.767 回答
1

我已经确定了一个解决我的问题的解决方案,强制 A 和 B 存在于数组中,尽管在位置上这样做,因此需要以某种方式对我正在验证的 JSON 对象进行排序。

工作模式


{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Order dependent solution",

  "type": "array",
  "items": [
    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "title": "A Object",

      "type": "object",
      "required": ["id", "name"],

      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string",
          "enum": ["A"]
        }
      },
      "additionalProperties": false
    },
    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "title": "B Object",

      "type": "object",
      "required": ["id", "name"],

      "properties": {
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string",
          "enum": ["B"]
        }
      },
      "additionalProperties": false
    }
  ],

  "additionalItems": {

    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "C Object",

    "type": "object",
    "required": ["id", "name"],

    "properties": {
      "id": {
        "type": "integer"
      },
      "name": {
        "type": "string"
      }
    },
    "additionalProperties": false  
  }

}

此 JSON 模式验证一个 JSON 数组,该数组包含索引 0 处的 A 对象、索引 1 处的 B 对象和构成所有剩余元素的 C 对象。这个解决方案是可用的,并且允许我继续开发,尽管更喜欢一个独立于订单的解决方案。

任何帮助表示赞赏!:)

PS - 这些模式没有优化,并展示了冗余,我将在最终版本中使用“id”和“$ref”关键字将其删除。

于 2013-11-06T13:58:20.923 回答