Валидация числовых значений в JSON Schema строится вокруг набора базовых ограничений, среди которых ключевую роль играют границы диапазона. Для строгого контроля используются параметры минимального и максимального значения, а также их «эксклюзивные» варианты, исключающие сами граничные значения из допустимого диапазона.
При описании числовых полей применяются четыре основных ключа:
Включительные границы допускают совпадение значения с порогом. Исключающие границы запрещают равенство, требуя строгого выхода за пределы.
Пример включительной границы:
{
"type": "number",
"minimum": 10
}
Допустимыми считаются значения 10, 11, 12 и так далее.
Исключающая граница изменяет поведение:
{
"type": "number",
"exclusiveMinimum": 10
}
Здесь 10 уже не проходит проверку, минимально допустимое значение становится строго больше 10.
Важная деталь заключается в эволюции спецификации.
В Draft-07 и ранее exclusiveMinimum и exclusiveMaximum задавались как булевы флаги, связанные с minimum и maximum:
{
"type": "number",
"minimum": 10,
"exclusiveMinimum": true
}
Это означало: минимум 10, но 10 не включается.
Начиная с Draft 2019-09 и далее (включая 2020-12), модель изменилась. exclusiveMinimum и exclusiveMaximum стали самостоятельными числовыми значениями:
{
"type": "number",
"exclusiveMinimum": 10
}
Теперь 10 — это строгая нижняя граница, а допустимые значения начинаются с 10 + ε (в практическом смысле — 10 не включается).
Такая смена модели устранила неоднозначность и сделала схему более выразительной.
Библиотека Ajv строго следует спецификации выбранного draft-режима. Поведение exclusiveMinimum и exclusiveMaximum зависит от версии схемы, указанной при инициализации валидатора.
import Ajv fr om "ajv";
const ajv = new Ajv({
strict: true
});
Ajv автоматически определяет поведение ключей в зависимости от meta-schema.
const schema = {
type: "number",
exclusiveMinimum: 0
};
const validate = ajv.compile(schema);
validate(-1); // false
validate(0); // false
validate(0.1); // true
Здесь 0 полностью исключён из диапазона.
const schema = {
type: "number",
exclusiveMaximum: 100
};
const validate = ajv.compile(schema);
validate(100); // false
validate(99.9); // true
Граница 100 становится недостижимой точкой.
В современных схемах Draft 2019-09+ использование minimum вместе с exclusiveMinimum запрещено как конфликтующее выражение.
Неправильная комбинация:
{
"type": "number",
"minimum": 5,
"exclusiveMinimum": 10
}
Здесь возникает логическое противоречие: нижняя включительная граница ниже исключающей.
Ajv в строгом режиме фиксирует такие ошибки на этапе компиляции схемы.
Эксклюзивные границы особенно важны для дробных чисел:
const schema = {
type: "number",
exclusiveMinimum: 1.5,
exclusiveMaximum: 2.5
};
Допустимый диапазон:
Поведение зависит от точности floating-point, что требует осторожности при математически точных вычислениях.
Для целочисленных ограничений комбинация с multipleOf часто используется для формирования дискретных диапазонов:
const schema = {
type: "integer",
exclusiveMinimum: 0,
exclusiveMaximum: 10,
multipleOf: 1
};
Допустимые значения: 1–9.
При включённой опции преобразования типов:
const ajv = new Ajv({
coerceTypes: true
});
строковые значения могут автоматически приводиться к числам:
validate("5"); // будет преобразовано в 5
Это влияет и на проверку границ: после приведения применяются правила exclusiveMinimum и exclusiveMaximum.
Ajv возвращает структурированные ошибки:
validate(0).errors;
Типичная ошибка:
{
"keyword": "exclusiveMinimum",
"params": {
"comparison": ">",
"limit": 0
},
"message": "must be greater than 0"
}
Для exclusiveMaximum сообщение аналогично, но с условием “<”.
Всегда считается невалидным для type: number.
Зависит от конфигурации и режима строгой проверки. В большинстве случаев:
Не проходит проверку number, если не указано:
"nullable": true
или union типов:
{ "type": ["number", "null"] }
{
type: "number",
exclusiveMinimum: 0,
exclusiveMaximum: 1,
multipleOf: 0.2
}
Формирует дискретный набор:
0.2, 0.4, 0.6, 0.8
Граница 1 не включается.
Хотя pattern применяется к строкам, в сочетании с type: “string” и преобразованиями типов можно косвенно влиять на числовую логику, например при сериализации.
Ajv компилирует схемы в JavaScript-функции. Проверка exclusiveMinimum и exclusiveMaximum сводится к прямым числовым сравнениям:
Такая реализация обеспечивает минимальные накладные расходы даже при массовой валидации больших массивов данных.
При включённом code generation оптимизации исключаются лишние проверки, если схема содержит только один из диапазонных ключей.
{
"exclusiveMinimum": 100,
"exclusiveMaximum": 10
}
Логически невозможный диапазон.
{
"minimum": 10,
"exclusiveMinimum": 10
}
Конфликт спецификации, запрещённый в строгом режиме Ajv.
{
"exclusiveMinimum": 0
}
Без type: “number” поведение может быть неопределённым в зависимости от контекста схемы.
Минимальные комиссии, проценты, ставки:
{
type: "number",
exclusiveMinimum: 0,
maximum: 1
}
Температуры, скорости, массы с недостижимыми границами:
{
type: "number",
exclusiveMinimum: -273.15
}
Настройки производительности, таймауты:
{
type: "integer",
exclusiveMinimum: 0,
maximum: 10000
}
Эксклюзивные границы формируют строгую математическую модель допустимых значений, устраняя неоднозначность включения порогов и обеспечивая детерминированное поведение валидации при использовании Ajv и JSON Schema.