48. ValidationPipe - Class Validator y Class Transformer

 

Validación de Datos en NestJS con ValidationPipe, Class-Validator y Class-Transformer

Cuando desarrollamos APIs, una de las tareas más comunes -y a veces tediosas- es validar que los datos que recibimos en las peticiones cumplan con ciertos estándares. ¿No sería genial tener una forma sencilla y automatizada de hacer esto? En NestJS, podemos lograrlo con el ValidationPipe junto con las librerías class-validator y class-transformer.

Antes: Validación Manual

Originalmente, nuestro controlador de autos (cars.controller.ts) aceptaba cualquier dato sin validación:

typescript
Copy
Download
import { Controller, Get, Param, Post, Body, Patch, Delete, ParseIntPipe } from '@nestjs/common';
import { CarsService } from './cars.service';
import { CreateCarDto } from './dto/create-car.dto';

@Controller('cars')
export class CarsController {
  constructor(private readonly carsService: CarsService) {}

  @Get()
  getAllCars() {
    return this.carsService.findAll();
  }

  @Get(':id')
  getCarById(@Param('id') id: string) {
    return this.carsService.findOneById(+id);
  }

  @Post()
  createCar(@Body() createCarDto: CreateCarDto) {
    return createCarDto;
  }

  @Patch(':id')
  updateCar(
    @Param('id', ParseIntPipe) id: number,
    @Body() body: any
  ) {
    return body;
  }

  @Delete(':id')
  deleteCar(@Param('id', ParseIntPipe) id: number) {
    return {
      method: 'delete',
      id
    };
  }
}

Y nuestro DTO (create-car.dto.ts) era simplemente una clase sin validaciones:

typescript
Copy
Download
export class CreateCarDto {
  readonly Brand: string;
  readonly model: string;
}

Configurando las Validaciones

Para implementar validaciones automáticas, primero instalamos las dependencias necesarias:

bash
Copy
Download
yarn add class-validator class-transformer

Después: Validación Automática

Ahora, podemos decorar nuestro DTO con validadores:

typescript
Copy
Download
import { IsString } from 'class-validator';

export class CreateCarDto {
  @IsString({ message: 'The Brand must be a cool string' })
  readonly Brand: string;
  
  @IsString()
  readonly model: string;
}

Y aplicamos el ValidationPipe en nuestro controlador:

typescript
Copy
Download
import { Controller, Get, Param, Post, Body, Patch, Delete, ParseIntPipe, UsePipes, ValidationPipe } from '@nestjs/common';
import { CarsService } from './cars.service';
import { CreateCarDto } from './dto/create-car.dto';

@Controller('cars')
export class CarsController {
  constructor(private readonly carsService: CarsService) {}

  @Get()
  getAllCars() {
    return this.carsService.findAll();
  }

  @Get(':id')
  getCarById(@Param('id') id: string) {
    return this.carsService.findOneById(+id);
  }

  @Post()
  @UsePipes(ValidationPipe)
  createCar(@Body() createCarDto: CreateCarDto) {
    return createCarDto;
  }

  @Patch(':id')
  updateCar(
    @Param('id', ParseIntPipe) id: number,
    @Body() body: any
  ) {
    return body;
  }

  @Delete(':id')
  deleteCar(@Param('id', ParseIntPipe) id: number) {
    return {
      method: 'delete',
      id
    };
  }
}

Beneficios de este Enfoque

  1. Validación automática: NestJS validará automáticamente que los datos cumplan con las reglas definidas.

  2. Mensajes personalizados: Podemos definir mensajes de error específicos para cada validación.

  3. Código más limpio: Elimina la necesidad de escribir manualmente validaciones repetitivas.

  4. Tipado seguro: Mantenemos el tipado TypeScript en todo nuestro flujo de datos.

Decoradores Comunes de Class-Validator

Algunos de los decoradores más útiles incluyen:

  • @IsOptional() - El campo es opcional

  • @IsPositive() - Debe ser un número positivo

  • @IsString() - Debe ser una cadena de texto

  • @IsEmail() - Debe ser un email válido

  • @IsUrl() - Debe ser una URL válida

  • @IsArray() - Debe ser un arreglo

  • @IsDate() - Debe ser una fecha válida

  • @IsBoolean() - Debe ser un valor booleano

Próximos Pasos

En una próxima publicación, veremos cómo configurar el ValidationPipe a nivel global para aplicarlo a todos los controladores automáticamente, evitando tener que decorar cada método individualmente.

¿Qué opinas de este enfoque para la validación de datos? ¿Lo has implementado en tus proyectos? ¡Déjame saber en los comentarios

Comentarios

Entradas más populares de este blog

32-Modulos

49. Pipes Globales - A nivel de Aplicación