Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

class-transformer — Sztuka transformacji danych

Straż bramy nie tylko sprawdza, kto wchodzi — czasem musi też przebrać przybysza w odpowiednią togę lub zabrać mu zbędne przedmioty. Dokładnie tym zajmuje się class-transformer — biblioteką do kontrolowania, jak dane są transformowane między różnymi formatami.

Podstawowe koncepcje

class-transformer oferuje dwa główne kierunki transformacji:

1// plain object → class instance
2const legionary = plainToInstance(CreateLegionaryDto, requestBody);
3
4// class instance → plain object
5const plainObject = instanceToPlain(legionary);

@Exclude() — ukryj wrażliwe dane

Najczęściej używany dekorator. Ukrywa pole przy konwersji obiektu na odpowiedź JSON. To jak strażnik, który zatrzymuje poufne dokumenty:

1import { Exclude } from 'class-transformer';
2
3export class LegionaryResponseDto {
4  name: string;
5  rank: string;
6
7  @Exclude()
8  secretMissionCode: string;  // To pole NIE pojawi się w odpowiedzi
9
10  @Exclude()
11  salary: number;  // Żołd też jest tajny
12}

Żeby to działało, kontroler musi używać serializacji:

1import { UseInterceptors, ClassSerializerInterceptor } from '@nestjs/common';
2
3@UseInterceptors(ClassSerializerInterceptor)
4@Controller('legionaries')
5export class LegionaryController {
6  @Get(':id')
7  findOne(@Param('id') id: string) {
8    // secretMissionCode i salary zostaną ukryte
9    return this.service.findOne(id);
10  }
11}

@Expose() — kontroluj widoczność pól

Odwrotność

@Exclude()
. Gdy użyjesz strategii
excludeAll
, tylko pola z
@Expose()
będą widoczne:

1import { Exclude, Expose } from 'class-transformer';
2
3@Exclude()
4export class LegionaryResponseDto {
5  @Expose()
6  name: string;    // Widoczne
7
8  @Expose()
9  rank: string;    // Widoczne
10
11  salary: number;  // UKRYTE (bo cała klasa ma @Exclude)
12  secretCode: string;  // UKRYTE
13}

@Transform() — niestandardowa transformacja

Pozwala zdefiniować własną logikę transformacji pola:

1import { Transform } from 'class-transformer';
2
3export class CreateLegionaryDto {
4  @Transform(({ value }) => value.trim().toLowerCase())
5  name: string;
6  // " MARCUS  " → "marcus"
7
8  @Transform(({ value }) => new Date(value))
9  enlistmentDate: Date;
10
11  @Transform(({ value }) => Math.round(value))
12  experienceYears: number;
13}

@Type() — transformacja typów zagnieżdżonych

Gdy masz zagnieżdżone obiekty,

@Type()
mówi class-transformer, na jaką klasę skonwertować:

1import { Type } from 'class-transformer';
2
3class WeaponDto {
4  name: string;
5  damage: number;
6}
7
8export class LegionaryDto {
9  name: string;
10
11  @Type(() => WeaponDto)
12  weapon: WeaponDto;
13  // { name: "Gladius", damage: 50 } → instancja WeaponDto
14}

plainToInstance i instanceToPlain

Te funkcje pozwalają ręcznie transformować dane:

1import { plainToInstance, instanceToPlain } from 'class-transformer';
2
3// Z zwykłego obiektu na instancję klasy
4const rawData = { name: 'Marcus', rank: 'centurio' };
5const legionary = plainToInstance(CreateLegionaryDto, rawData);
6// Teraz legionary jest instancją klasy z walidacją
7
8// Z instancji klasy na zwykły obiekt
9const plain = instanceToPlain(legionary);
10// Pola z @Exclude() zostaną usunięte

Praktyczny przykład — DTO z transformacjami

1import { Exclude, Expose, Transform, Type } from 'class-transformer';
2import { IsString, IsNumber } from 'class-validator';
3
4export class CreateLegionaryDto {
5  @IsString()
6  @Transform(({ value }) => value.trim())
7  name: string;
8
9  @IsString()
10  rank: string;
11
12  @IsNumber()
13  age: number;
14}
15
16export class LegionaryResponseDto {
17  @Expose()
18  name: string;
19
20  @Expose()
21  rank: string;
22
23  @Expose()
24  @Transform(({ value }) =>
25    value > 10 ? 'Weteran' : 'Rekrut'
26  )
27  experienceLevel: string;
28
29  @Exclude()
30  internalCode: string;
31}

class-transformer to potężne narzędzie, które daje ci pełną kontrolę nad tym, jak dane wchodzą i wychodzą z twojego API. W połączeniu z class-validator tworzysz nieprzeniknioną ochronę bramy!

Przejdź do CodeWorlds