Уникальность элементов массива в JSON Schema реализуется через
ключевое слово uniqueItems, поддерживаемое библиотекой Ajv
и используемое для контроля отсутствия дубликатов внутри массивов
данных.
Ключ uniqueItems: true накладывает ограничение на
массив: каждый его элемент должен быть уникальным относительно
остальных. При валидации Ajv выполняет попарное сравнение элементов
массива и фиксирует нарушение при обнаружении хотя бы одной
повторяющейся пары.
Основной принцип работы:
Важным аспектом является то, что уникальность определяется не только по примитивным значениям, но и по структурам данных.
Для проверки уникальности Ajv использует строгую семантику сравнения:
number, string,
boolean, null) сравниваются по значению;Таким образом, два объекта с одинаковыми полями и значениями считаются дубликатами, даже если это разные ссылки в памяти.
Пример:
{
"type": "array",
"uniqueItems": true,
"items": {
"type": "object",
"properties": {
"id": { "type": "number" }
},
"required": ["id"]
}
}
Данные:
[
{ "id": 1 },
{ "id": 1 }
]
Результат валидации: ошибка уникальности.
Поведение uniqueItems становится особенно значимым при
работе со сложными структурами.
При проверке объектов учитываются все свойства. Порядок ключей не влияет на результат, так как сравнение выполняется по нормализованной структуре данных.
[
{ "a": 1, "b": 2 },
{ "b": 2, "a": 1 }
]
Элементы считаются идентичными.
Массивы сравниваются по длине и поэлементно:
[
[1, 2],
[1, 2]
]
Такие элементы трактуются как дубликаты.
В современных версиях Ajv применяется оптимизация проверки уникальности для повышения производительности при работе с большими массивами.
Основные механизмы:
Для примитивных значений проверка часто сводится к использованию хеш-структур, что уменьшает сложность с квадратичной до линейной в типичных случаях.
Особенности JavaScript влияют на результаты проверки:
NaN не равен самому себе по стандартному сравнению, но
Ajv учитывает его как одинаковое значение при сериализации;-0 и 0 считаются эквивалентными;undefined в JSON отсутствует, но в промежуточных
структурах может учитываться при кастомной обработке.Глубокая вложенность увеличивает стоимость проверки уникальности. Например:
[
{ "data": { "items": [1, 2, 3] } },
{ "data": { "items": [1, 2, 3] } }
]
Такие элементы требуют рекурсивного обхода всей структуры, что влияет на производительность при больших объёмах данных.
При нарушении uniqueItems Ajv формирует объект ошибки,
содержащий:
Ошибки не агрегируются по всем парам, а фиксируются по факту обнаружения конфликта, что снижает нагрузку при обработке больших массивов.
В строгом режиме (strict: true) поведение
uniqueItems становится более предсказуемым:
Это особенно важно при работе с динамическими API, где структура входящих данных может изменяться.
Механизм uniqueItems имеет ряд ограничений:
В случаях, когда стандартного uniqueItems недостаточно,
применяются дополнительные схемы контроля:
enum для фиксированных наборов
значений;const для жёстко заданных структур;addKeyword для
реализации собственной логики уникальности.Пример кастомной проверки:
ajv.addKeyword({
keyword: "uniqueById",
validate: function (schema, data) {
const ids = new Set();
for (const item of data) {
if (ids.has(item.id)) return false;
ids.add(item.id);
}
return true;
}
});
Такой подход позволяет ограничить уникальность по конкретному полю, а не по всей структуре объекта.
При проектировании схем с uniqueItems учитываются
следующие факторы:
В высоконагруженных системах часто выполняется предварительная дедупликация на уровне бизнес-логики, а не через JSON Schema, что снижает нагрузку на валидатор Ajv.