Валидация числовых значений в Ajv опирается на спецификацию JSON
Schema, где числовой тип разделяется на два базовых варианта: целые
числа и числа с плавающей точкой. Различие между ними формально задаётся
через ключ type, принимающий значения
"integer" или "number".
Внутренне Ajv проверяет соответствие значений типу JavaScript
number, однако логика валидации учитывает дополнительные
ограничения схемы, накладываемые JSON Schema, включая диапазоны,
кратность и строгие типовые проверки.
Тип "integer" в JSON Schema описывает числа без дробной
части. В контексте JavaScript это означает проверку на отсутствие
остатка от деления на 1.
В Ajv целочисленная проверка реализуется через проверку
Number.isInteger().
Пример схемы:
{
"type": "integer"
}
Такая схема допускает значения:
И отклоняет:
Особенность заключается в том, что JavaScript не имеет отдельного
целочисленного типа, поэтому различие между integer и
number носит логический, а не физический характер.
Дополнительно к типу могут применяться ограничения:
{
"type": "integer",
"minimum": 0,
"maximum": 100
}
Такая схема задаёт диапазон допустимых целых значений от 0 до 100 включительно.
Тип "number" включает все числовые значения JavaScript,
включая целые и дробные. Проверка осуществляется без требования
целочисленности.
Пример схемы:
{
"type": "number"
}
Допустимые значения:
При этом важно учитывать, что все числа в JavaScript представлены в формате IEEE 754 double precision, что приводит к особенностям округления и точности.
Ajv не исправляет и не нормализует такие значения, а работает с тем, что передано интерпретатором.
Для числовых типов в Ajv применяются стандартные ключи JSON Schema:
minimummaximumexclusiveMinimumexclusiveMaximumПример:
{
"type": "number",
"minimum": 0,
"maximum": 1
}
Эта схема ограничивает значения интервалом [0, 1].
Использование строгих границ:
{
"type": "number",
"exclusiveMinimum": 0,
"exclusiveMaximum": 1
}
В зависимости от версии JSON Schema и настроек Ajv,
exclusiveMinimum и exclusiveMaximum могут
задаваться как числа или как объекты:
{
"type": "number",
"exclusiveMinimum": {
"value": 0
}
}
Ajv учитывает версию спецификации (draft-07, 2019-09 и новее), что влияет на интерпретацию этих полей.
Ключ multipleOf задаёт кратность числового значения.
Проверка выполняется через деление числа на заданный множитель с учётом
погрешности floating point.
Пример:
{
"type": "number",
"multipleOf": 0.5
}
Допустимые значения:
Недопустимые:
Ajv использует внутренние механизмы сравнения с учётом машинной точности, что особенно важно при работе с дробными множителями.
Все числовые значения в JavaScript представлены как IEEE 754 double precision floating point. Это приводит к ряду эффектов:
Ajv не выполняет арифметическую коррекцию значений, а полагается на результат вычислений JavaScript.
При использовании multipleOf, minimum,
maximum сравнения выполняются через стандартные операции
<, >, === с учётом
особенностей IEEE 754.
Ajv поддерживает опцию coerceTypes, которая позволяет
автоматически преобразовывать входные данные к ожидаемому типу
схемы.
При включении:
const ajv = new Ajv({ coerceTypes: true });
возможны преобразования:
"10" → 10"3.14" → 3.14При этом для integer выполняется дополнительная проверка
после преобразования:
"10" → 10 → допустимо"10.5" → 10.5 → отклоняется при типе
integerПриведение типов не устраняет логические ограничения схемы, а лишь приводит данные к числовому представлению перед валидацией.
Ajv формирует структурированные ошибки при нарушении числовых ограничений. Ошибки содержат:
instancePath)keyword)Пример типичной ошибки:
{
"instancePath": "/age",
"keyword": "minimum",
"message": "should be >= 18",
"params": {
"comparison": ">=",
"limit": 18
}
}
Для числовых типов возможны ошибки:
type (не число или не integer)minimummaximummultipleOfСхема с целым числом и диапазоном:
{
"type": "object",
"properties": {
"age": {
"type": "integer",
"minimum": 0,
"maximum": 120
}
}
}
Схема с вещественным числом и точностью:
{
"type": "object",
"properties": {
"temperature": {
"type": "number",
"minimum": -273.15,
"multipleOf": 0.01
}
}
}
Схема с автоматическим приведением типов:
{
"type": "object",
"properties": {
"price": {
"type": "number"
}
},
"required": ["price"]
}
При включённом coerceTypes значение "19.99"
будет интерпретировано как число.
Допускается комбинирование типов через массив:
{
"type": ["integer", "number"]
}
В такой конструкции значение проходит валидацию, если оно является
числом, независимо от наличия дробной части. Однако семантически это
редко используется, поскольку integer уже является
подмножеством number.
Более строгая модель разделения обычно достигается явным указанием типа в каждой схеме свойства, а не объединением типов.