Валидация длины значений в JSON Schema опирается на набор стандартных ключевых слов, которые позволяют строго контролировать размер строк, массивов и объектов. В библиотеке Ajv эти ограничения реализованы напрямую через спецификацию JSON Schema Draft 7/2019-09/2020-12 и обрабатываются на этапе компиляции схемы в оптимизированный валидатор.
Для строковых значений используются ключевые слова:
Оба ограничения применяются к количеству символов в строке, однако важно учитывать, что в JavaScript строка представлена в UTF-16, и длина считается в кодовых единицах, а не в «человеческих символах» (графемах).
{
"type": "string",
"minLength": 3,
"maxLength": 10
}
Такая схема допускает строки длиной от 3 до 10 символов включительно.
Ajv возвращает структурированную ошибку:
{
"instancePath": "/username",
"schemaPath": "#/properties/username/minLength",
"keyword": "minLength",
"params": {
"limit": 3
},
"message": "must NOT have fewer than 3 characters"
}
Сообщения можно кастомизировать через messages или через
ajv-errors, но сами проверки остаются неизменными.
Одной из ключевых проблем при работе с ограничениями длины является различие между:
Ajv использует стандартное поведение Jav * aScript:
"?".length === 2
Это означает, что emoji или символы вне BMP (Basic Multilingual Plane) считаются как два символа.
Пример:
{
"type": "string",
"maxLength": 2
}
Строка "?" будет считаться длиной 2 и пройдет
валидацию, хотя визуально это один символ.
Для корректной работы с реальной «человеческой длиной» требуется предварительная нормализация данных или использование кастомных валидаторов.
Для массивов используются:
{
"type": "array",
"minItems": 1,
"maxItems": 5,
"items": {
"type": "number"
}
}
Такая схема ограничивает массив от 1 до 5 чисел.
Ajv проверяет длину массива через .length, без
дополнительных преобразований:
length = 0length = 3Ошибки имеют вид:
{
"keyword": "maxItems",
"params": {
"limit": 5
},
"message": "must NOT have more than 5 items"
}
При использовании фиксированной схемы массива:
{
"type": "array",
"items": [
{ "type": "string" },
{ "type": "number" }
],
"additionalItems": false
}
ограничение длины становится косвенным: массив не может содержать более двух элементов.
Таким образом, additionalItems: false часто используется
как альтернативный способ ограничения длины.
Для объектов применяются:
{
"type": "object",
"minProperties": 2,
"maxProperties": 4
}
Эта схема ограничивает количество свойств объекта.
Ajv считает только собственные перечисляемые ключи объекта. Наследуемые свойства не учитываются.
Пример:
const obj = Object.create({ inherited: true });
obj.a = 1;
obj.b = 2;
Для схемы:
{ "minProperties": 2 }
объект будет валиден, поскольку учитываются только a и
b.
Ограничения длины часто комбинируются с другими правилами:
{
"type": "string",
"minLength": 5,
"maxLength": 20,
"pattern": "^[a-zA-Z0-9_]+$"
}
Здесь порядок проверки в Ajv оптимизирован:
Если длина не проходит, pattern не вычисляется, что
повышает производительность.
{
"type": "array",
"minItems": 2,
"maxItems": 10,
"items": {
"type": "string",
"minLength": 3
}
}
Здесь ограничения применяются на двух уровнях:
Ajv при компиляции схемы преобразует ограничения длины в оптимизированные JavaScript-функции без промежуточных абстракций.
Пример внутренней логики:
minLength → сравнение числа
(str.length >= N)maxLength → сравнение числа
(str.length <= N)minItems → arr.length >= NЭто позволяет добиться минимальной стоимости проверки.
В строгом режиме Ajv (strict: true) дополнительно
проверяет:
Пример конфликтной схемы:
{
"type": "string",
"minLength": 10,
"maxLength": 5
}
В строгом режиме такая схема может вызвать предупреждение при компиляции, поскольку условия взаимоисключающие.
{
"type": "string",
"minLength": 0
}
Эквивалентно отсутствию ограничения, но формально фиксирует допустимость пустой строки.
Ограничения длины не применяются к null. Для этого
требуется:
{
"type": ["string", "null"],
"maxLength": 10
}
{
"type": "string",
"minLength": 5
}
Строка "12345" валидна, но число 12345
должно быть предварительно приведено к строке, иначе будет ошибка
типа.
Ajv позволяет расширять поведение через пользовательские ключевые слова:
ajv.addKeyword({
keyword: "byteLength",
type: "string",
validate: function (schema, data) {
return Buffer.byteLength(data, "utf8") <= schema;
}
});
Такой подход решает проблему UTF-16 длины и позволяет работать с реальными байтовыми ограничениями.
Наиболее частая проблема — ожидание, что length
соответствует байтам или визуальным символам.
{
"type": "array",
"maxItems": 3,
"items": {
"type": "array",
"maxItems": 2
}
}
Ограничения применяются рекурсивно, но каждая вложенная структура проверяется отдельно.
{
"minItems": 5,
"maxItems": 2
}
Такие схемы логически недостижимы, но Ajv выполнит их без автоматического исправления, оставляя ответственность за разработчиком.
Для повышения производительности при массовой валидации:
maxLength как первую линию защиты для
строкpattern + format + length, если достаточно одного
ограниченияAjv компилирует схемы в функции, поэтому упрощение структуры напрямую влияет на скорость выполнения.
Ограничения длины представляют собой базовый слой валидации, который:
length, Object.keys().length)Их корректное использование формирует основу строгой и предсказуемой схемы данных в JSON Schema, обеспечивая стабильность валидации на уровне структуры и содержимого.