I have a controller that needs to receive data in the request query string (I can't use the body because I'm interacting with a legacy system).
I wrote a DTO map query params to an object and I'm using a ValidationPipe to validate and transform the data to my DTO.
So, I have this:
import { Get, Controller, Query, Post, Body, UsePipes, ValidationPipe } from '@nestjs/common';
class TestDto {
@IsNumber()
field1: number;
@IsBoolean()
field2: boolean;
}
@Controller()
export class AppController {
constructor() {}
@Get()
@UsePipes(new ValidationPipe({ whitelist: false, transform: true}))
root(@Query() dto: TestDto): TestDto {
return dto;
}
}
All of the previous code compìles and follows the NestJS documentation, but when I call http://localhost:3000/?field1=15&field2=true I get this:
{
"statusCode": 400,
"error": "Bad Request",
"message": [
{
"target": {
"field1": "15",
"field2": "true"
},
"value": "15",
"property": "field1",
"children": [],
"constraints": {
"isNumber": "field1 must be a number"
}
},
{
"target": {
"field1": "15",
"field2": "true"
},
"value": "true",
"property": "field2",
"children": [],
"constraints": {
"isBoolean": "field2 must be a boolean value"
}
}
]
}
Both fields are valid according to the attributes but the pipe rejects the request. If I change from @IsNumber to @IsNumberString and from @IsBoolean to @IsBooleanString it validates, but I do not received the transformed data (i.e. I get a plain object instead of my DTO)
Did anybody face something like this?
It cannot, as interfaces only shape your structure or tell something about type. You validation will not work correctly due to the same fact.
class TestDto
See NestJS docs - Auto Validation NestJS docs - Payload transforming
As example in docs say:
import { IsEmail, IsNotEmpty } from 'class-validator'; // 'class'
export class CreateUserDto { // notice class
@IsEmail()
email: string;
@IsNotEmpty()
password: string;
}
Update #1 - tell validator to try to make implicit conversion
@UsePipes( new ValidationPipe( { transform: true, transformOptions: {enableImplicitConversion: true} }))
Update #2 - use custom @Query()
param decorator
import { Controller, createParamDecorator, Get, UsePipes, ValidationPipe } from '@nestjs/common';
import { IsNumber } from 'class-validator';
import { AppService } from './app.service';
const MyField = createParamDecorator((data, req) => {
const result = new TestDto();
result.field1 = Number(req.query.field1);
return result;
});
class TestDto {
@IsNumber()
field1: number;
}
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {
}
@Get()
@UsePipes(new ValidationPipe({ transform: true }))
getHello(@MyField() testDto: TestDto): TestDto {
return testDto;
}
}
Another option is to enable implicit conversion.
@UsePipes(new ValidationPipe({ transform: true, transformOptions: { enableImplicitConversion: true } }))
You can use app.useGlobalPipes(new ValidationPipe({ transform: true }));
on main.ts too. It's work for me 😊
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With