In NestJS, serialization refers to the process of converting an object into a format suitable for storage or transmission. This typically involves transforming an object’s state to ensure safe transfer over a network or persistent storage. While NestJS does not provide built-in serialization functionality, you can achieve serialization and validation using third-party libraries like class-transformer and class-validator.
Installing Dependencies
First, install class-transformer and class-validator:
npm install class-transformer class-validatorCreating DTO Class
A DTO (Data Transfer Object) class is used to represent data transfer objects, typically for serialization and deserialization. Below is an example of a simple DTO class for user data.
// src/users/dto/user.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { Expose } from 'class-transformer';
import { IsEmail, IsString, IsNotEmpty } from 'class-validator';
export class UserDto {
@ApiProperty()
@Expose()
@IsString()
@IsNotEmpty()
public id: string;
@ApiProperty()
@Expose()
@IsString()
@IsNotEmpty()
public firstName: string;
@ApiProperty()
@Expose()
@IsString()
@IsNotEmpty()
public lastName: string;
@ApiProperty()
@Expose()
@IsEmail()
@IsNotEmpty()
public email: string;
// This property will not be serialized
@ApiProperty({ readOnly: true })
@IsString()
@IsNotEmpty()
private _password: string;
// Getter method to expose password
get password(): string {
return this._password;
}
// Setter method to set password
set password(value: string) {
this._password = value;
}
}In this example, the @Expose() decorator specifies which properties should be serialized. The _password property is private and accessed via getter and setter methods, allowing control over when and how the password is exposed.
Serialization and Deserialization
Next, create a service to handle serialization and deserialization processes.
// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { UserDto } from './dto/user.dto';
@Injectable()
export class UsersService {
async createUser(userDto: UserDto): Promise<UserDto> {
// Add business logic here, e.g., saving to a database
return userDto;
}
async getUser(id: string): Promise<UserDto> {
// Add business logic here, e.g., fetching from a database
const user = new UserDto();
user.id = id;
user.firstName = 'John';
user.lastName = 'Doe';
user.email = 'john.doe@example.com';
user.password = 'secret'; // Password will not be serialized
return user;
}
}Serialization in Controllers
In a controller, use the DTO class to receive and return data.
// src/users/users.controller.ts
import { Controller, Post, Body, Get, Param } from '@nestjs/common';
import { UsersService } from './users.service';
import { UserDto } from './dto/user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly userService: UsersService) {}
@Post()
async createUser(@Body() userDto: UserDto): Promise<UserDto> {
return this.userService.createUser(userDto);
}
@Get(':id')
async getUser(@Param('id') id: string): Promise<UserDto> {
return this.userService.getUser(id);
}
}Testing Serialization
To test serialization, use tools like Postman to send requests to the API.
Create User
Send a POST request to the /users endpoint with user data:
{
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"password": "secret"
}Get User
Send a GET request to /users/:id, e.g., /users/1. The response should exclude the password information.
Excluding Specific Properties
To completely exclude certain properties from serialization, use the @Exclude() decorator:
// src/users/dto/user.dto.ts
import { Exclude } from 'class-transformer';
// ...
export class UserDto {
// ...
@Exclude()
private _password: string;
// ...
}Explicit Conversion
For explicit conversion during serialization, use the plainToClass and classToPlain methods provided by class-transformer:
// src/users/users.service.ts
import { plainToClass } from 'class-transformer';
// ...
@Injectable()
export class UsersService {
async createUser(userDto: UserDto): Promise<UserDto> {
// Add business logic here, e.g., saving to a database
return userDto;
}
async getUser(id: string): Promise<UserDto> {
const plainUser = {
id: id,
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@example.com',
password: 'secret', // Password will not be serialized
};
return plainToClass(UserDto, plainUser);
}
}



