@Body Reads Parsed JSON From the Client
The Request Body
POST, PUT, and PATCH usually carry a JSON payload. `@Body` exposes it to your handler, typed if you want.
What you'll learn
- Use `@Body()` to read the whole body
- Use `@Body('field')` to read a single key
- Use a DTO class to type the body
For write requests (POST, PUT, PATCH) the payload arrives as the
HTTP body. Nest auto-parses JSON and hands it to your handler through
the @Body() decorator.
Reading the Whole Body
import { Controller, Post, Body } from '@nestjs/common';
@Controller('users')
export class UsersController {
@Post()
create(@Body() body: { name: string; email: string }) {
return this.users.create(body);
}
} Send JSON to POST /users and body is the parsed object. Nest
configures the body parser for you with sensible defaults (1 MB JSON
limit by default).
Picking a Single Field
If you only need one key, name it:
@Post('rename')
rename(@Body('name') name: string) {
return this.users.rename(name);
} Handy for tiny endpoints. For anything with multiple fields, prefer a DTO so validation and types are explicit.
Use a DTO for Typed, Validated Bodies
A DTO (Data Transfer Object) is a class that describes the shape of the
input. Combined with class-validator decorators and a global
ValidationPipe, you get runtime checks for free:
import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@IsString() @MinLength(2)
name!: string;
@IsEmail()
email!: string;
} @Post()
create(@Body() dto: CreateUserDto) {
return this.users.create(dto);
} Bad input (name too short, malformed email) gets a structured 400
response — your handler never runs.
Why Classes, Not Interfaces
TypeScript interfaces vanish at compile time, so Nest can’t see them at
runtime. Classes survive, and that’s what class-validator reads. Always
use a class for DTOs even though you’ll be tempted to use an interface.
Quick Test
curl -X POST http://localhost:3000/users \
-H 'content-type: application/json' \
-d '{"name":"Ada","email":"ada@example.com"}' Returns the new user. Try sending an invalid email and you’ll see a 400
with the validation error message — courtesy of the ValidationPipe you
turn on in main.ts.