Структура схемы

Базовые элементы схемы

JSON Schema представляет собой декларативное описание структуры данных. В экосистеме Ajv схема используется как входная спецификация для компиляции валидатора, который затем проверяет соответствие данных заданным правилам.

Минимальная схема может выглядеть следующим образом:

{
  "type": "object"
}

Ключ type определяет базовый тип значения. В рамках JSON Schema поддерживаются следующие основные типы:

  • string
  • number
  • integer
  • boolean
  • object
  • array
  • null

Комбинирование этих типов формирует основу строгой типизации данных.


Описание объектной структуры

При работе с объектами ключевым элементом становится свойство properties. Оно задаёт допустимые поля и их схемы:

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  }
}

Каждое свойство внутри properties является самостоятельной схемой. Это означает возможность рекурсивного описания вложенных структур любой глубины.

Обязательные поля

Ключ required определяет список обязательных свойств:

{
  "type": "object",
  "properties": {
    "id": { "type": "string" },
    "email": { "type": "string" }
  },
  "required": ["id"]
}

Важно: required применяется только к именам свойств, а не к их значениям.

Контроль дополнительных свойств

additionalProperties управляет тем, разрешены ли поля, не описанные в properties:

  • true — разрешены любые дополнительные поля
  • false — строгий режим без лишних ключей
  • схема — валидация дополнительных свойств по указанной схеме
{
  "type": "object",
  "properties": {
    "id": { "type": "string" }
  },
  "additionalProperties": false
}

Массивы и структура элементов

Для массивов используется ключ items, определяющий схему элементов:

{
  "type": "array",
  "items": {
    "type": "number"
  }
}

Каждый элемент массива проверяется по указанной схеме.

Кортежная структура

JSON Schema допускает фиксированную структуру массива:

{
  "type": "array",
  "items": [
    { "type": "string" },
    { "type": "number" }
  ]
}

В этом случае первый элемент должен быть строкой, второй — числом.

Ограничение длины массива

Дополнительные ключи:

  • minItems
  • maxItems
  • uniqueItems

Пример:

{
  "type": "array",
  "minItems": 1,
  "maxItems": 5,
  "uniqueItems": true
}

Ветвления логики: oneOf, anyOf, allOf

Сложные структуры описываются через композиционные операторы.

allOf

Все схемы должны быть валидны одновременно:

{
  "allOf": [
    { "type": "object" },
    { "required": ["id"] }
  ]
}

oneOf

Данные должны соответствовать ровно одной схеме:

{
  "oneOf": [
    { "type": "string" },
    { "type": "number" }
  ]
}

anyOf

Допускается соответствие хотя бы одной схемы:

{
  "anyOf": [
    { "type": "string" },
    { "type": "boolean" }
  ]
}

Ссылки и переиспользование схем

Одним из ключевых механизмов является $ref, позволяющий ссылаться на повторно используемые определения.

{
  "$ref": "#/definitions/address"
}

Определения размещаются в definitions:

{
  "definitions": {
    "address": {
      "type": "object",
      "properties": {
        "city": { "type": "string" },
        "zip": { "type": "string" }
      }
    }
  }
}

В более современных спецификациях также применяется $defs, но принцип остаётся идентичным: централизованное переиспользование блоков схем.


Идентификация и метаданные схемы

Служебные поля:

  • $id — уникальный идентификатор схемы
  • $schema — версия спецификации JSON Schema
  • title — человекочитаемое имя
  • description — описание структуры

Пример:

{
  "$id": "https://example.com/schemas/user",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "User",
  "type": "object"
}

Эти поля не участвуют в валидации данных напрямую, но влияют на организацию и интерпретацию схем.


Ограничения значений

Для примитивных типов используются дополнительные ограничения.

Строки

  • minLength
  • maxLength
  • pattern
  • format
{
  "type": "string",
  "minLength": 3,
  "pattern": "^[a-zA-Z]+$"
}

Числа

  • minimum
  • maximum
  • exclusiveMinimum
  • exclusiveMaximum
  • multipleOf
{
  "type": "number",
  "minimum": 0,
  "maximum": 100
}

Перечисления значений

Ключ enum задаёт фиксированный набор допустимых значений:

{
  "type": "string",
  "enum": ["admin", "user", "guest"]
}

Этот механизм часто используется для строгих доменных ограничений.


Вложенность и рекурсивные структуры

JSON Schema поддерживает рекурсивные описания через ссылки:

{
  "$ref": "#/definitions/node",
  "definitions": {
    "node": {
      "type": "object",
      "properties": {
        "value": { "type": "string" },
        "children": {
          "type": "array",
          "items": { "$ref": "#/definitions/node" }
        }
      }
    }
  }
}

Такая структура применяется при описании деревьев, графов и сложных иерархий.


Влияние структуры схемы на поведение Ajv

В Ajv структура схемы напрямую влияет на этап компиляции. Схема преобразуется в оптимизированную функцию проверки, где:

  • типы проверяются первыми
  • ограничения группируются по приоритету
  • $ref разрешаются в процессе компиляции
  • композиционные операторы трансформируются в логические ветвления

Грамотно структурированная схема снижает глубину проверок и ускоряет выполнение валидатора.


Детерминированность описания

JSON Schema в контексте Ajv требует строгой формализации:

  • отсутствие неявных типов
  • явное описание всех ветвлений
  • минимизация конфликтующих правил
  • предсказуемая структура вложенности

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