JSON Схема: проверка массива пользовательских объектов $ ref'd - PullRequest
1 голос
/ 05 мая 2020

Фон: Привет! Я пытался работать над схемой, которая проверяет, что массив внутри объекта содержит только некоторые из объектов, которые были определены внутри моего definitions блока.

В качестве примера , У меня есть следующие JSON данные для проверки:

{
   "component_type":"section",
   "component_properties":{
      "section_name":"first_section",
      "fields":[
         {
            "component_type":"spacer",
            "component_properties":{
               "width":6
            }
         },
         {
            "component_type":"textbox",
            "component_properties":{
               "display_text":"hello!",
               "text_color":"black"
            }
         },
         {
            "component_type":"spacer",
            "component_properties":{
               "width":3
            }
         }
      ]
   }
}

Идея этих данных заключается в том, что существует section «компонент», определенный на самом высоком уровне, заполненный подкомпонентами, которые также определены для проверки (spacer, textbox).

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

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "properties": {
    "component_type": {
      "type": "string",
      "const": "section"
    },
    "component_properties": {
      "type": "object",
      "properties": {
        "section_name": { "type": "string"},
        "sections": {
          "type": "array",
          "oneOf": [
            { "$ref": "#/definitions/section_field" },
            { 
              "type": "array",
              "items": {
                "$ref": "#/definitions/section_field"
              }
            }
          ]
        }
      }
    }
  },
  "definitions": {
    "spacer": {
      "type": "object",
      "properties": {
        "component_type": {
          "type": "string",
          "const": "spacer"
        },
        "component_properties": {
          "width": "number"
        }
      }
    },
    "textbox": {
      "type": "object",
      "properties": {
        "component_type": {
          "type": "string",
          "const": "textbox"
        },
        "component_properties": {
          "display_text": "hello!",
          "text_color": "purple"
        }
      }
    },
    "section_field": {
      "oneOf": [
        {
          "$ref": "#/definitions/spacer"
        },
        {
          "$ref": "#/definitions/textbox"
        }
      ]
    }
  }
}

Эта схема не гарантирует, что все элементы внутри массива «fields» свойства component_properties на уровне раздела имеют поле "component_type": "spacer" или "component_type": "textbox". Например, "component_type": "another_one" не должно пройти проверку.

Пожалуйста, дайте мне знать, если какая-либо дополнительная информация будет полезна! Я был бы очень признателен за некоторые рекомендации здесь.

1 Ответ

0 голосов
/ 05 мая 2020

Ваша схема почти в порядке - за исключением следующих деталей:

  1. ”type”: “array” внутри свойства sections следует удалить. Должен остаться только ”oneOf”. В противном случае первая часть "oneOf" (единственный элемент) никогда не будет действительной.
  2. "component_properties" должно быть "type": "object", а затем перечислить width / display_text / text_color в это "properties". Похоже, вы только что скопировали содержимое примера.

Однако ваша схема принимает ваш пример из-за опечатки:

  • В вашем примере у вас есть fields свойство. Но в вашей схеме он называется sections. Я предполагаю, что он должен называться fields в обоих.

Поскольку ни одно из свойств не помечено как required, данный пример подтверждает правильность. Для свойства fields нет ограничений. Если вы отметите sections как required, он будет жаловаться.


В общем, следующая версия вашей схемы должна делать то, что вы хотите:

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "type": "object",
  "required": ["component_type", "component_properties"],
  "properties": {
    "component_type": { "const": "section" },
    "component_properties": {
      "type": "object",
      "required": ["section_name", "fields"],
      "properties": {
        "section_name": { "type": "string" },
        "fields": {
          "oneOf": [
            { "$ref": "#/definitions/section_field" },
            { 
              "type": "array",
              "items": { "$ref": "#/definitions/section_field" }
            }
          ]
        }
      }
    }
  },
  "definitions": {
    "spacer": {
      "type": "object",
      "required": ["component_type", "component_properties"],
      "properties": {
        "component_type": { "const": "spacer" },
        "component_properties": {
          "properties": {
            "width": { "type": "number" }
          }
        }
      }
    },
    "textbox": {
      "type": "object",
      "required": ["component_type", "component_properties"],
      "properties": {
        "component_type": { "const": "textbox" },
        "component_properties": {
          "type": "object",
          "properties": {
            "display_text": { "type": "string" },
            "text_color": { "type": "string" }
          }
        }
      }
    },
    "section_field": {
      "oneOf": [
        { "$ref": "#/definitions/spacer" },
        { "$ref": "#/definitions/textbox" }
      ]
    }
  }
}
...