@IsISBN — декоратор библиотеки Class-validator, предназначенный для проверки корректности значений ISBN (International Standard Book Number). Используется для валидации строк, представляющих книжные идентификаторы форматов ISBN-10 и ISBN-13, с поддержкой проверки контрольной цифры и допустимых символов.
ISBN существует в двух основных вариантах:
Старый формат, состоящий из 10 символов. Последний символ может быть
цифрой или символом X, который обозначает значение 10 в
контрольной сумме.
Пример:
0306406152
0-306-40615-2
0 306 40615 2
Современный формат, состоящий из 13 цифр. Начинается с префиксов
978 или 979.
Пример:
9780306406157
978-0-306-40615-7
978 0 306 40615 7
Декоратор поддерживает оба варианта при соответствующей конфигурации.
@IsISBN(version?: number)
version (необязательный): определяет допустимую
версию ISBN
10 — только ISBN-1013 — только ISBN-13import { IsISBN } from 'class-validator';
export class BookDto {
@IsISBN()
isbn: string;
}
В данном случае допустимыми считаются как ISBN-10, так и ISBN-13.
import { IsISBN } from 'class-validator';
export class BookDto {
@IsISBN(10)
isbn: string;
}
import { IsISBN } from 'class-validator';
export class BookDto {
@IsISBN(13)
isbn: string;
}
При несоответствии версии значение считается невалидным, даже если формат строки корректен.
Внутренняя логика проверки включает несколько этапов:
Допускаются разделители:
-Они удаляются перед проверкой контрольной суммы.
X на последней позиции для
ISBN-10)Используется взвешенная сумма:
(1×d1 + 2×d2 + ... + 10×d10) % 11 === 0
Если последний символ X, он интерпретируется как 10.
Используется алгоритм с коэффициентами 1 и 3:
(d1 + 3×d2 + d3 + 3×d4 + ... ) % 10 === 0
123456789
978030640615
0-306-40615-3
978-0-306-40615-8
978-0-306-40A15-7
ISBN9780306406157
import { IsISBN } from 'class-validator';
export class BookDto {
@IsISBN(13, {
message: 'ISBN должен соответствовать формату ISBN-13',
})
isbn: string;
}
Сообщение переопределяет стандартный текст ошибки, генерируемый валидатором.
Перед валидацией часто выполняется нормализация строки:
export class BookDto {
@IsISBN()
isbn: string;
}
const dto = new BookDto();
dto.isbn = input.trim();
Для более сложных случаев используется явная очистка:
dto.isbn = input.replace(/[\s-]/g, '');
import { IsNotEmpty, IsISBN } from 'class-validator';
export class BookDto {
@IsNotEmpty()
@IsISBN(13)
isbn: string;
}
import { IsString, IsISBN } from 'class-validator';
export class BookDto {
@IsString()
@IsISBN()
isbn: string;
}
Порядок декораторов не влияет на результат валидации, но влияет на структуру ошибок.
import { IsISBN } from 'class-validator';
export class BookDto {
@IsISBN(13, { groups: ['create'] })
isbn: string;
}
@Validate(BookDto, { groups: ['create'] })
Группы позволяют разделять сценарии, например создание и обновление сущности.
В сочетании с ValidateIf:
import { ValidateIf, IsISBN } from 'class-validator';
export class BookDto {
@ValidateIf(o => o.format === 'book')
@IsISBN()
isbn: string;
format: string;
}
При несоответствии условия поле пропускается.
Символ X допускается только на последней позиции:
class BookDto {
@IsISBN(10)
isbn: string;
}
Допустимо:
030640615X
Недопустимо:
X306406152
ISBN часто копируется с префиксами:
ISBN 978-0-306-40615-7
Такие строки требуют предварительной очистки.
Смешивание пробелов и дефисов не всегда критично, но дополнительные символы ломают валидацию.
Некоторые источники предоставляют устаревший формат, который не
проходит проверку при @IsISBN(13).
При использовании в DTO NestJS:
import { IsISBN } from 'class-validator';
export class CreateBookDto {
@IsISBN(13)
isbn: string;
}
валидация выполняется автоматически через
ValidationPipe:
app.useGlobalPipes(new ValidationPipe());
При ошибке возвращается стандартный HTTP-ответ с описанием нарушений.
При необходимости расширенной логики:
import { registerDecorator, ValidationOptions } from 'class-validator';
export function IsValidBookISBN(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: 'isValidBookISBN',
target: object.constructor,
propertyName,
options: validationOptions,
validator: {
validate(value: any) {
return typeof value === 'string' && value.length > 0;
},
},
});
};
}
Если не используются дополнительные декораторы:
undefined и null обычно пропускаются@IsNotEmpty() или
@IsDefined()@IsDefined()
@IsISBN()
isbn: string;
@IsISBN работает в средах:
Основная зависимость — библиотека class-validator,
использующая внутренние алгоритмы проверки ISBN без внешних API.