Сериализация ответов
Сериализация — превращение объекта в JSON перед отправкой клиенту. По умолчанию NestJS отправляет объект целиком, со всеми полями. Встроенный перехватчик ClassSerializerInterceptor вместе с библиотекой class-transformer позволяет пометить в сущности поля, которые нельзя показывать, — например, хеш пароля.
Пометка полей
Библиотека class-transformer уже установлена в уроке о валидации. Добавьте декоратор @Exclude() к паролю:
// src/users/entities/user.entity.ts
import { Exclude } from 'class-transformer';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column()
name: string;
@Exclude()
@Column()
password: string;
@Column({ default: 'user' })
role: string;
}Сам по себе декоратор ничего не меняет: он лишь помечает поле для перехватчика.
Включение перехватчика
Перехватчик включают для всего приложения в src/main.ts:
// src/main.ts
import { ClassSerializerInterceptor, ValidationPipe } from '@nestjs/common';
import { NestFactory, Reflector } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();Теперь контроллер регистрации может вернуть сущность целиком:
// src/users/users.controller.ts
@Post()
register(@Body() dto: CreateUserDto) {
return this.usersService.create(dto);
}Отправьте POST /users — в ответе будут id, email, name и role, а поля password не будет. Ручное перечисление полей из урока о пользователях больше не нужно.
Вычисляемые поля
Декоратор @Expose() над геттером добавляет в ответ поле, которого нет в базе:
// src/posts/entities/post.entity.ts
import { Expose } from 'class-transformer';
@Expose()
get excerpt(): string {
return this.content.slice(0, 100);
}В ответах со статьями появится поле excerpt — первые 100 символов текста.
Основные декораторы
| Декоратор | Что делает |
|---|---|
@Exclude() | Убирает поле из ответа |
@Expose() | Добавляет в ответ геттер или поле |
@Transform(({ value }) => ...) | Меняет значение поля перед отправкой |
@Type(() => Comment) | Указывает класс вложенных объектов |
Частая ошибка
Перехватчик работает только с объектами классов. Если сервис вернёт обычный объект, например { ...user } или результат JSON.parse(), пометок @Exclude() у него нет, и пароль уйдёт клиенту. Возвращайте сущности, полученные из репозитория, а если нужно собрать ответ вручную — создавайте объект класса через plainToInstance(User, data) из class-transformer.