Cómo funciona la serialización en Nest
La serialización en NestJS es el proceso mediante el cual los objetos JavaScript se transforman en un formato que puede ser transmitido a través de la red, típicamente JSON. Este mecanismo es fundamental para controlar qué datos se envían al cliente y cómo se estructuran las respuestas de la API.
NestJS implementa la serialización a través de interceptores que se ejecutan automáticamente antes de enviar la respuesta al cliente. El framework utiliza la librería class-transformer
para realizar estas transformaciones, permitiendo un control granular sobre el proceso de serialización.
Interceptor de serialización automática
Por defecto, NestJS aplica serialización automática a todas las respuestas de los controladores. Cuando un método de controlador retorna un objeto, el framework lo convierte automáticamente a JSON:
@Controller('users')
export class UsersController {
@Get()
findAll(): User[] {
// Este array se serializa automáticamente a JSON
return [
{ id: 1, name: 'Juan', email: 'juan@email.com', password: 'secret123' },
{ id: 2, name: 'María', email: 'maria@email.com', password: 'secret456' }
];
}
}
El problema con este enfoque es que todos los campos del objeto se incluyen en la respuesta, incluyendo información sensible como contraseñas.
Control de campos con decoradores
Para controlar qué campos se incluyen en la serialización, NestJS utiliza decoradores de class-transformer
. El decorador @Exclude()
permite omitir campos específicos:
import { Exclude } from 'class-transformer';
export class User {
id: number;
name: string;
email: string;
@Exclude()
password: string;
@Exclude()
createdAt: Date;
}
También puedes usar @Expose()
para incluir únicamente los campos marcados, excluyendo todos los demás por defecto:
import { Expose } from 'class-transformer';
export class UserResponseDto {
@Expose()
id: number;
@Expose()
name: string;
@Expose()
email: string;
// password y otros campos se excluyen automáticamente
}
Transformación de datos durante la serialización
La serialización también permite transformar los datos antes de enviarlos. Puedes modificar valores, cambiar nombres de propiedades o crear campos calculados:
import { Transform, Expose } from 'class-transformer';
export class User {
@Expose()
id: number;
@Expose()
@Transform(({ value }) => value.toUpperCase())
name: string;
@Expose()
email: string;
@Expose()
@Transform(({ obj }) => `${obj.name} <${obj.email}>`)
displayName: string;
@Exclude()
password: string;
}
Serialización condicional
Puedes aplicar serialización condicional basada en diferentes criterios como roles de usuario o contexto de la petición:
import { Expose, Transform } from 'class-transformer';
export class User {
@Expose()
id: number;
@Expose()
name: string;
@Expose()
email: string;
@Expose({ groups: ['admin'] })
password: string;
@Expose({ groups: ['admin', 'owner'] })
createdAt: Date;
}
Para usar grupos en el controlador, especifica el grupo en las opciones de serialización:
@Controller('users')
export class UsersController {
@Get()
@SerializeOptions({ groups: ['admin'] })
findAll(): User[] {
return this.usersService.findAll();
}
}
Anidación y relaciones
La serialización maneja automáticamente objetos anidados y relaciones entre entidades. Puedes controlar cómo se serializan las relaciones:
import { Expose, Type } from 'class-transformer';
export class Post {
@Expose()
id: number;
@Expose()
title: string;
@Expose()
@Type(() => User)
author: User;
@Expose()
@Type(() => Comment)
comments: Comment[];
}
export class Comment {
@Expose()
id: number;
@Expose()
content: string;
@Exclude()
authorId: number;
}
Configuración global de serialización
Puedes configurar el comportamiento de serialización a nivel global en el archivo principal de la aplicación:
import { ClassSerializerInterceptor } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Configuración global del interceptor de serialización
app.useGlobalInterceptors(
new ClassSerializerInterceptor(app.get(Reflector), {
strategy: 'excludeAll', // Excluir todo por defecto
excludeExtraneousValues: true, // Excluir valores no definidos
enableImplicitConversion: true // Conversión automática de tipos
})
);
await app.listen(3000);
}
Esta configuración asegura que la serialización se aplique consistentemente en toda la aplicación, proporcionando un control uniforme sobre las respuestas de la API y mejorando la seguridad al evitar la exposición accidental de datos sensibles.
Fuentes y referencias
Documentación oficial y recursos externos para profundizar en Nest
Documentación oficial de Nest
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Nest es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Nest
Explora más contenido relacionado con Nest y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
- Comprender el concepto de serialización en NestJS y su importancia.
- Aprender a utilizar interceptores para la serialización automática de respuestas.
- Controlar qué campos se incluyen o excluyen en la serialización mediante decoradores.
- Aplicar transformaciones y serialización condicional según contexto o roles.
- Configurar la serialización globalmente y manejar objetos anidados y relaciones entre entidades.