Skip to main content
nestrs DTO validation combines serde for deserialization with the validator crate for constraint checking. The #[dto] macro derives both automatically; ValidationPipe or ValidatedBody<T> runs the validation before your handler receives the data. Invalid payloads return 422 Unprocessable Entity with a structured error body.

#[dto]

Derives serde::Deserialize, validator::Validate, and NestDto on a struct. By default it also emits #[serde(deny_unknown_fields)] so any JSON key not in the struct definition causes a 422 error.

#[dto(allow_unknown_fields)]

Opts out of deny_unknown_fields. Use this when you intentionally accept JSON payloads from forward-compatible clients that may include extra fields.
Do not manually add #[serde(deny_unknown_fields)] to a struct that already uses #[dto]—the macro applies it by default and duplicating the attribute causes a compile error.

NestDto trait

NestDto is a marker trait generated by #[dto]. It is used by ValidationPipe and the ValidatedBody<T>, ValidatedQuery<T>, and ValidatedPath<T> extractors to enforce that only DTOs marked with #[dto] are passed through the validation pipeline.
You do not implement NestDto manually; #[dto] handles it.

Using DTOs in handlers

Field validation attributes

All field attributes are applied inside a #[dto] struct. They expand to validator crate constraint annotations.

String constraints

#[IsString]
attribute
Validates that the field is a non-empty string. Useful as a presence check when used with String.
#[IsEmail]
attribute
Validates that the field is a well-formed email address.
#[IsUrl]
attribute
Validates that the field is a well-formed URL.
#[Length(min = N, max = N)]
attribute
Validates string length. Both min and max are optional.

Numeric constraints

#[IsInt]
attribute
Validates that the field is an integer type (i8i128, u8u128, isize, usize).
#[IsNumber]
attribute
Validates that the field is a numeric type (also accepts f32, f64).
#[Min(N)]
attribute
Validates that the numeric field is greater than or equal to N.
#[Max(N)]
attribute
Validates that the numeric field is less than or equal to N.

Boolean and optional

#[IsBoolean]
attribute
Validates that the field is a bool.
#[IsOptional]
attribute
Marks the field as optional in the validation pipeline. Wrap the field type in Option<T> and add this attribute so that a missing JSON key is accepted without triggering other validators on the field.

Nested DTOs

#[ValidateNested]
attribute
Runs validation recursively on a nested struct field. The nested type must also derive Validate (which #[dto] provides).

Comprehensive example

The following DTO covers string, numeric, boolean, optional, and nested validation in a single type:

deny_unknown_fields default behavior

#[dto] applies #[serde(deny_unknown_fields)] by default. This means any JSON key in the request body that is not a field on the struct causes deserialization to fail with a 422 response before validation even runs.
This is intentional and matches NestJS’s ValidationPipe behavior with whitelist: true. Use #[dto(allow_unknown_fields)] when you need to accept extra fields from clients on a different schema version.