Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Сериализация ответов

Сериализация — превращение объекта в 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.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.