Диапазоны значений

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

Базовые числовые ограничения

Для числовых значений используются ключи:

  • minimum — минимально допустимое значение
  • maximum — максимально допустимое значение
  • exclusiveMinimum — исключение нижней границы
  • exclusiveMaximum — исключение верхней границы

Простейшая схема диапазона выглядит следующим образом:

{
  "type": "number",
  "minimum": 10,
  "maximum": 20
}

Такая схема допускает любые числа от 10 до 20 включительно.

Включительные и исключительные границы

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

Включительные границы:

{
  "type": "number",
  "minimum": 10,
  "maximum": 20
}

Исключительные границы:

{
  "type": "number",
  "exclusiveMinimum": 10,
  "exclusiveMaximum": 20
}

В этом случае допустимы значения строго больше 10 и строго меньше 20.

Также возможно комбинирование:

{
  "type": "number",
  "minimum": 10,
  "exclusiveMaximum": 20
}

Такой вариант допускает 10, но исключает 20.

Особенности работы exclusiveMinimum и exclusiveMaximum

В современных версиях JSON Schema (и, соответственно, Ajv) допускается использование числовых значений для exclusiveMinimum и exclusiveMaximum, что позволяет задавать границы без отдельного ключа minimum или maximum.

Пример:

{
  "type": "number",
  "exclusiveMinimum": 10
}

Здесь все значения должны быть строго больше 10.

Аналогично:

{
  "type": "number",
  "exclusiveMaximum": 100
}

Диапазоны для целых чисел

Ограничения диапазона одинаково применимы к типу integer:

{
  "type": "integer",
  "minimum": 1,
  "maximum": 100
}

Дополнительно можно комбинировать с проверкой кратности:

{
  "type": "integer",
  "minimum": 0,
  "maximum": 100,
  "multipleOf": 5
}

Такое описание ограничивает значения числами 0, 5, 10, …, 100.

Связь диапазонов с типизацией

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

Пример:

{
  "type": "number",
  "minimum": 0
}

Строка "10" не будет автоматически преобразована в число и не пройдёт валидацию.

Ограничения диапазонов для строк

Хотя термин «диапазон» чаще относится к числам, в JSON Schema аналогичная логика применяется к строкам через свойства:

  • minLength
  • maxLength

Пример:

{
  "type": "string",
  "minLength": 5,
  "maxLength": 10
}

Такое ограничение задаёт допустимую длину строки.

Диапазоны массивов

Для массивов применяются аналогичные концепции:

  • minItems
  • maxItems
{
  "type": "array",
  "minItems": 1,
  "maxItems": 5
}

Это задаёт диапазон количества элементов.

Сочетание диапазонов с другими ограничениями

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

Пример комбинированной схемы:

{
  "type": "object",
  "properties": {
    "age": {
      "type": "integer",
      "minimum": 18,
      "maximum": 65
    },
    "score": {
      "type": "number",
      "exclusiveMinimum": 0,
      "maximum": 100
    }
  },
  "required": ["age", "score"]
}

Здесь одновременно задаются разные типы диапазонов для разных полей.

Поведение при нарушении диапазона

При нарушении границ Ajv формирует объект ошибки, содержащий:

  • путь к значению (instancePath)
  • тип нарушения (keyword)
  • ожидаемое ограничение (params)
  • сообщение (message)

Пример ошибки при выходе за пределы:

{
  "instancePath": "/age",
  "keyword": "minimum",
  "params": {
    "comparison": ">=",
    "limit": 18
  }
}

Производительность проверки диапазонов

Проверки диапазонов являются одними из наиболее быстрых операций в Ajv, поскольку:

  • не требуют рекурсивной обработки структуры
  • выполняются на уровне примитивного сравнения
  • оптимизируются при компиляции схемы

Особенно эффективно работают схемы с фиксированными границами, так как компилятор Ajv превращает их в прямые сравнения без дополнительных абстракций.

Расширенные сценарии использования диапазонов

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

  • валидация возраста пользователя
  • ограничение ценовых значений
  • контроль координат (широта/долгота)
  • лимиты пагинации (page, limit)
  • контроль процентных значений

Пример пагинации:

{
  "type": "object",
  "properties": {
    "page": {
      "type": "integer",
      "minimum": 1
    },
    "limit": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    }
  }
}

Взаимодействие диапазонов с форматами

Диапазоны могут комбинироваться с форматами данных:

{
  "type": "number",
  "minimum": 0,
  "maximum": 1,
  "format": "float"
}

Однако формат не влияет на проверку диапазона, он используется отдельно для семантической интерпретации значения.

Ошибки проектирования диапазонов

Типичные проблемы при использовании диапазонов:

  • отсутствие верхней границы, приводящее к неограниченному росту значений
  • конфликт minimum и maximum (например, minimum > maximum)
  • использование строк вместо чисел без явного преобразования
  • избыточно узкие диапазоны, ограничивающие валидные данные

Пример некорректной схемы:

{
  "type": "number",
  "minimum": 50,
  "maximum": 10
}

Такая схема логически противоречива и приведёт к невозможности прохождения валидации.

Итеративное уточнение диапазонов

В сложных системах диапазоны часто уточняются постепенно:

  1. базовый широкий диапазон
  2. уточнение бизнес-логикой
  3. адаптация под реальные данные
  4. фиксация финальных ограничений в схеме

Такой подход позволяет избежать преждевременного ужесточения правил и снижает количество ошибок валидации на ранних этапах разработки.