Проблема проверки массива JSON при использовании oneOf - PullRequest
0 голосов
/ 05 февраля 2019

Надеюсь, я мог бы найти некоторую помощь в этой проблеме проверки: у меня есть массив JSON, который может иметь несколько типов объектов (видео, изображение).Внутри этого массива объекты имеют значение поля rel.Случай, над которым я работаю, состоит в том, что может быть только один объект с разрешенным "rel": "primaryMedia" - или видео или изображением.

Здесь представлены представления объектов для случая с изображением и видео, оба из которых показывают "rel": "primaryMedia".

{
  "media": [
    {
      "caption": "Caption goes here",
      "id": "ncim87659842",
      "rel": "primaryMedia",
      "type": "image"
    },
    {
      "description": "Shaima Swileh arrived in San Francisco after fighting for 17 months to get a waiver from the U.S. government to be allowed into the country to visit her son.",
      "headline": "Yemeni mother arrives in U.S. to be with dying 2-year-old son",
      "id": "mmvo1402810947621",
      "rel": "primaryMedia",
      "type": "video"
    }
  ]
}

Вот урезанная версия схемы, которую я создал, чтобы проверить это с помощью oneOf (при условии, что это подойдет для моего случая).Однако он не работает должным образом.

{
  "$id": "http://example.com/schema/rockcms/article.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {},
  "properties": {
    "media": {
      "items": {
        "oneOf": [
          {
            "additionalProperties": false,
            "properties": {
              "caption": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "rel": {
                "enum": [
                  "primaryMedia"
                ],
                "type": "string"
              },
              "type": {
                "enum": [
                  "image"
                ],
                "type": "string"
              }
            },
            "required": [
              "caption",
              "id",
              "rel",
              "type"
            ],
            "type": "object"
          },
          {
            "additionalProperties": false,
            "properties": {
              "description": {
                "type": "string"
              },
              "headline": {
                "type": "string"
              },
              "id": {
                "type": "string"
              },
              "rel": {
                "enum": [
                  "primaryMedia"
                ],
                "type": "string"
              },
              "type": {
                "enum": [
                  "video"
                ],
                "type": "string"
              }
            },
            "required": [
              "description",
              "headline",
              "id",
              "rel",
              "type"
            ],
            "type": "object"
          }
        ]
      },
      "type": "array"
    }
  }
}

При использовании средства проверки схемы JSON на https://www.jsonschemavalidator.net, схема проверяет правильность представления данных, но не работает при попытке перехватаошибки.

В приведенном ниже случае для видео добавляется headline, а отсутствует id.Это должно произойти, потому что headline не разрешено для видео, и id требуется.

{ 
  "media": [
    {
      "headline": "Yemeni mother arrives in U.S. to be with dying 2-year-old son",
      "rel": "primaryMedia",
      "type": "video"
    }
  ]
}

Результаты, полученные от валидатора, однако, не совсем ожидаемы.Похоже, что в своем ответе он объединяет две объектные схемы.

В дополнение к этому, я отдельно обнаружил, что схема позволит заполнить ОБА объект видео и изображения в media, что не ожидается.

Попыткавыяснить, что я сделал не так, но тупик.Буду очень признателен за некоторые отзывы, если кто-то может предложить.Заранее спасибо!


Ответ валидатора:

Сообщение: JSON действителен в отсутствие схем из 'oneOf'.Путь к схеме: # / properties / media / items / oneOf

Сообщение: свойство 'headline' не определено, и схема не допускает дополнительные свойства.Путь к схеме: # / properties / media / items / oneOf / 0 / AdditionalProperties

Сообщение: значение enum не определено.Путь к схеме: # / properties / media / items / oneOf / 0 / properties / type / enum

Сообщение: в объекте отсутствуют обязательные свойства: description, id.Путь к схеме: # / properties / media / items / oneOf / 1 / required

Сообщение: в объекте отсутствуют обязательные свойства: caption, id.Путь к схеме: # / properties / media / items / oneOf / 0 / обязательный

1 Ответ

0 голосов
/ 05 февраля 2019

Ваш вопрос состоит из трех частей, но первые две связаны, поэтому я рассмотрю их, хотя у них нет «решения» как такового.

  1. Как я могу проверить, что только один объект в массиве имеет определенный ключ, а другие нет.

Вы не можете сделать это с помощью схемы JSON.Набор ключевых слов JSON Schema, применимых к массивам, не имеет средств для выражения «одно из значений должно соответствовать схеме», а скорее применим к ВСЕМ элементам в массиве или к элементу SPECIFIC вмассив (если items - это массив в отличие от объекта).https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4

Результат проверки не тот, который я ожидаю.Я ожидаю увидеть только ветвь с ошибкой oneOf, относящуюся к моему типу объекта, который определяется ключом type.

Спецификация схемы JSON (по состоянию на черновик7) не указывает какой-либо формат для возврата ошибок, однако полученная вами структура ошибок является довольно «полной» с точки зрения того, что она говорит вам (и аналогично тому, как мы указываем ошибки, которые должны быть возвращены для черновика-8).

Учтите, что валидатор ничего не знает о вашей схеме или экземпляре JSON с точки зрения вашей бизнес-логики.При проверке экземпляра JSON средство проверки может пройти по всем значениям и проверить правила проверки для всех применимых подсхем.Глядя на ваши ошибки, обе схемы в oneOf применимы ко всем элементам в вашем массиве, поэтому все они проверены на валидацию.Если один не удовлетворяет условию, другие будут также проверены.Валидатор не может знать, при использовании oneOf, каково было ваше намерение.

Вы МОЖЕТЕ обойти эту проблему, используя комбинацию if / then.Если ваша if схема является просто константой типа, а ваша then схема является полным типом объекта, вы можете получить более понятный ответ об ошибке, но я не проверял эту теорию.

Я хочу, чтобы ВСЕ элементы в массиве были одного из типов.Что здесь происходит?

Из спецификации ...

items:

Если "items" является схемой,проверка завершается успешно, если все элементы в массиве успешно проверяются по этой схеме.

oneOf:

Экземпляр успешно проверяется по этому ключевому слову, если он
успешно проверяетсяпо отношению только к одной схеме, определенной значением этого ключевого слова
.

То, что вы сделали, говорят: каждый элемент в массиве должен быть действительным в соответствии с [schemaA].SchemA: объект должен быть действительным в соответствии с одной из следующих схем: [схемы внутри oneOf].

Я вижу, как это сбивает с толку, когда вы думаете, что «элементы должны быть одним из следующих»,но items применяет схему значений к каждому из элементов в массиве независимо.

Чтобы заставить его делать то, что вы имеете в виду, переместите oneOf над items, а затем выполните рефакторинг одного из типов носителей.к схеме других элементов.

Вот схема sudo.

oneOf: [items: properties: type: const: image], [items: properties: type: image]

Дайте мне знать, если что-то из этого неясно, или у вас есть какие-либо дополнительные вопросы.

...