In NestJS, the @Body() decorator is used to extract the request body data. By default, NestJS uses Express or Fastify as the HTTP server, which are configured with an internal middleware to parse JSON request bodies.
When handling JSON requests that contain date fields in the request body, these date fields are typically parsed as strings. To convert these strings into JavaScript Date objects, we have several approaches.
Using Pipes for Conversion
NestJS's pipes feature allows for transforming and validating data before it reaches the controller handler. We can create a custom pipe to parse and validate date strings.
For example, consider a request body that includes a startDate field:
json{ "startDate": "2023-04-01" }
We can create a ParseDatePipe as follows:
typescriptimport { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; @Injectable() export class ParseDatePipe implements PipeTransform { transform(value: any): Date { // Ensure the input is a string and can be parsed into a date if (typeof value === 'string' && !isNaN(Date.parse(value))) { return new Date(value); } else { throw new BadRequestException('Invalid date format'); } } }
Then, in the controller, we can apply this pipe to the specific request body field:
typescriptimport { Controller, Post, Body } from '@nestjs/common'; import { ParseDatePipe } from './parse-date.pipe'; @Controller('events') export class EventsController { @Post() createEvent( // Apply ParseDatePipe to the startDate field @Body('startDate', ParseDatePipe) startDate: Date ) { // startDate is now a JavaScript Date object // Proceed with further business logic } }
Using Class Validators and Transformers
In more complex scenarios or when consistently handling dates across the application, we can use class validators (such as class-validator) and class transformers (such as class-transformer). These libraries integrate well with NestJS to provide robust validation and conversion capabilities for request bodies.
First, ensure the required packages are installed:
shnpm install class-validator class-transformer
Then, define a DTO (Data Transfer Object) and use decorators to declare how fields should be automatically converted and validated:
typescriptimport { IsDateString, IsNotEmpty } from 'class-validator'; import { Type } from 'class-transformer'; export class CreateEventDto { @IsNotEmpty() @IsDateString() readonly name: string; @Type(() => Date) // Use class-transformer to convert the field to Date @IsDateString() readonly startDate: Date; }
In the controller, apply this DTO using the @Body() decorator:
typescriptimport { Controller, Post, Body } from '@nestjs/common'; import { CreateEventDto } from './create-event.dto'; @Controller('events') export class EventsController { @Post() createEvent(@Body() createEventDto: CreateEventDto) { // createEventDto.startDate is now a JavaScript Date object // Proceed with further business logic } }
Remember to enable the global validation pipe in your main app.module.ts to automatically apply conversion and validation logic:
typescriptimport { Module } from '@nestjs/common'; import { APP_PIPE } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; @Module({ // ... providers: [ { provide: APP_PIPE, useClass: ValidationPipe, // Enable global validation pipe }, ], }) export class AppModule {}
Using class-validator and class-transformer enables your application to handle date field conversion and validation in a declarative manner, which is particularly useful when building applications with multiple date fields or complex validation requirements.