Схема JSON для обеспечения содержимого массива

Привет всем и спасибо заранее.

Я пытаюсь создать схему JSON для принудительного применения массива, чтобы содержать один объект A и B и объекты N C, где 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 - это любой допустимый объект JSON, содержащий только свойства "id" и "name", где "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 должно быть значением, содержащимся в поле перечисления, где перечисление содержит одно значение.

Моя самая полная схема на сегодняшний день:


{
  "$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 содержался в моем массиве.

Ответ 1

То, что вы ищете, называется "набор текста".

Если значением ключевого слова items является массив, то элементы в данных массива должны совпадать со схемой в соответствующей позиции. Дополнительные элементы (прошлый последний индекс) соответствуют additionalItems (или запрещены, если additionalItems - 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, которое будет обрабатывать это аккуратно.)

Немного более подробная демо-версия:

Ответ 2

Я определил решение, которое решает мою проблему, применяя, что 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, содержащий объект A в индексе 0, объект B в индексе 1 и объекты C, составляющие все остальные элементы. Это решение можно использовать и позволяет мне продвигаться вперед с развитием, хотя предпочтительным будет решение, независимое от заказа.

Любая помощь приветствуется!:)

PS. Эти схемы не оптимизированы и демонстрируют избыточность, которую я удалю в финальной версии, используя ключевое слово "id" и "$ ref".