在 nestjs 中,主要透過 Pipe 這個元件來做輸入資料格式的驗證與資料格式的轉換。
Pipe 主要針對 Controller 內部的 handler 的參數做處理。
透過 Pipe 元件, handler 的參數會被逐個依照指定的格式做檢查並且做轉換,格式化成系統內部需要的格式。轉換格式的概念叫作 Serialization ,是指依照特定格式去轉換資料。
nestjs Pipe 元件,主要是一個類別去實作 PipeTransform 介面。具體透過 transform 方法實做出轉換資料的細節。
第一個 ValidationPipe 是可以在 Dto 上面做驗證設定,透過 ValidationPipe 可以檢核出哪些欄位資料格式不符預期。 Parse系列的 Pipe 則是可以把輸入轉換成預期的格式。 DefaultValuePipe 則是可以把參數自動帶入預設值。
為了使用 ValidationPipe ,會需要加入 class-validator 與 class-transformer 套件做開發,安裝指令如下:
pnpm i -S class-validator class-transformer
create-cat.dto.ts 如下
import { IsString, IsInt } from 'class-validator';
export class CreateCatDto {
@IsString()
name: string;
@IsInt()
age: number;
@IsString()
breed: string;
}
可透過 validate.pipe.ts 如下實作來進行轉換與驗證
import { PipeTransform, Injectable, ArgumentMetadata, BadRequestException } from '@nestjs/common';
import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
@Injectable()
export class ValidationPipe implements PipeTransform<unknown> {
async transform(value: unknown, { metatype }: ArgumentMetadata) {
if (!metatype || !this.toValidate(metatype)) {
return value;
}
const object = plainToInstance(metatype, value);
const errors = await validate(object);
if (errors.length > 0) {
throw new BadRequestException('Validation failed');
}
return value;
}
private toValidate(metatype: Function): boolean {
const types: Function[] = [String, Boolean, Number, Array, Object];
return !types.includes(metatype);
}
}
套用的範圍有以下三種:
@Post()
@UsePipes(ValidationPipe)
createPet(@Body() createPetDto: CreatePetDto) {
return this.petsService.createPet(createPetDto);
}
@Controller('pets')
@UsePipes(ValidationPipe)
export class PetsController {
constructor(private readonly petsService: PetsService) {}
...
}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap()
如果是轉換內部值的 Pipe 需要特別寫入要轉換的物件之後如下:
@Get()
async findOne(@Query('id', ParseIntPipe) id: number) {
return this.catsService.findOne(id);
}
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
}),
);
app.useGlobalPipes(
new ValidationPipe({
transform: true,
})
);
nestjs 透過 Pipe 元件來把輸入的資料做驗證與轉換,分擔了資料格式化的邏輯。實務上,常常使用 ValidattionPipe 來對輸入做驗證,確保輸入如逾期。