JSON模式以强制执行数组内容

问题描述:

大家好,谢谢.

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

I am attempting to create a JSON schema to enforce an array to contain one A and B object and N C objects, where A and B are C objects and N is an integer inclusively between 0 and infinity.

因此:

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

全部有效:

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

无效.

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

To make clear, A and B must be present. C objects are optional, though you may have as many as you would like.

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"是字符串.

So a C object is any valid JSON object containing only the properties "id" and "name" where "id" is an integer and "name" is a string.

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对象的名称值必须是包含在枚举字段中的值,其中枚举包含单个值.

A and B objects differ from C objects in that there name value is enforced. The name value of an A object must be a value contained in the field enum, where enum contains a single value.

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


{
  "$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必须是C,但是我不确定如何强制在数组中至少包含A和B的单个实例.

This enforces that all objects contained within must be of type C, which A and B are, though I am unsure how to enforce that at least single instance of A and B are contained within my array.

您正在寻找的被称为元组键入".

What you are looking for is called "tuple typing".

如果items关键字的值是一个数组,则数组数据中的项必须与相应位置的模式匹配.其他项(过去的最后一个索引)由additionalItems匹配(如果additionalItemsfalse,则不允许使用).

If the value of the items keyword is an array, then the items in the array data must match up with the schema in the corresponding position. Additional items (past the last index) are matched by additionalItems (or are disallowed if additionalItems is false).

因此,大致上您想要的是这样的:

So, roughly what you want is something like:

{
    "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匹配).

If you want to ensure that A and B exist, then you simply specify a minimum length using minItems, so there are at least two items (which because of "tuple typing", must match up with A and B).

(这还假设A和B是数组中的第一项.如果这不是您想要的,那么它将变得更加复杂-尽管存在稍微更详细的实时演示:

Slightly more detailed live demo:

  • Valid: [A, B]
  • Invalid: [A, C]
  • Valid: [A, B, C, C]