JSON Схема - может ли проверка массивов / списков сочетаться с anyOf? - PullRequest
0 голосов
/ 28 марта 2020

У меня есть json документ, который я пытаюсь проверить с помощью этой формы:

...
"products": [{
    "prop1": "foo",
    "prop2": "bar"
  }, {
    "prop3": "hello",
    "prop4": "world"
  },
...

Существует несколько различных форм, которые может принимать объект. Моя схема выглядит следующим образом:

...
"definitions": {
  "products": {
    "type": "array",
    "items": { "$ref": "#/definitions/Product" },

  "Product": {
    "type": "object",
    "oneOf": [
      { "$ref": "#/definitions/Product_Type1" },
      { "$ref": "#/definitions/Product_Type2" }, 
      ...
    ]
  },

  "Product_Type1": {
    "type": "object",
    "properties": {
      "prop1": { "type": "string" },
      "prop2": { "type": "string" }
  },
  "Product_Type2": {
    "type": "object",
    "properties": {
      "prop3": { "type": "string" },
      "prop4": { "type": "string" }
  }
...

Кроме того, некоторые свойства отдельных объектов массива продуктов могут быть перенаправлены при дальнейшем использовании anyOf или oneOf.

I сталкиваюсь с проблемами в VSCode, используя встроенную схему проверки, где он выдает ошибки для каждого элемента в массиве products, которые не совпадают с Product_Type1.

Так что, кажется, валидатор фиксирует это сначала oneOf он обнаружил и не будет проверять ни один из других типов.

Я не нашел никаких ограничений для механизма oneOf на jsonschema.org. И здесь нет упоминаний о том, что он используется на странице, специально посвященной массивам: https://json-schema.org/understanding-json-schema/reference/array.html

Возможно ли то, что я пытаюсь сделать?

1 Ответ

1 голос
/ 28 марта 2020

Ваш общий подход в порядке. Давайте возьмем немного более простой пример, чтобы проиллюстрировать, что происходит не так.

Учитывая эту схему

{
  "oneOf": [
    { "properties": { "foo": { "type": "integer" } } },
    { "properties": { "bar": { "type": "integer" } } }
  ]
}

И этот экземпляр

{ "foo": 42 }

На первый взгляд это выглядит так соответствует /oneOf/0, а не oneOf/1. Фактически он соответствует обеим схемам, что нарушает однозначное ограничение, налагаемое oneOf, и oneOf не выполняется.

Помните, что каждое ключевое слово в JSON Schema является ограничением. Все, что явно не исключено схемой, разрешено. В схеме /oneOf/1 нет ничего, что говорит о том, что свойство "foo" не разрешено. И при этом не говорит, что "foo" требуется. Это говорит только о том, что если у экземпляра есть ключевое слово «foo», то это должно быть целое число.

Чтобы это исправить, вам понадобится required и, возможно, additionalProperties в зависимости от ситуации. Я покажу здесь, как вы будете использовать additionalProperties, но я рекомендую вам не использовать его, если вам не нужно, потому что у него есть некоторые проблемные c свойства.

{
  "oneOf": [
    {
      "properties": { "foo": { "type": "integer" } },
      "required": ["foo"],
      "additionalProperties": false
    },
    {
      "properties": { "bar": { "type": "integer" } },
      "required": ["bar"],
      "additionalProperties": false
    }
  ]
}
...