NestJS的Pipe是一個用于數據轉換和驗證的特殊裝飾器。Pipe可以應用于控制器(Controller)的處理方法(Handler)和中間件(Middleware),用于處理傳入的數據。它可以用來轉換和驗證數據,確保數據的有效性和一致性。
內置的 Pipe 是指在使用 NestJS 框架時,已經預定義好的一些管道,用于驗證和轉換傳入的數據。
- ValidationPipe(驗證管道):用于驗證傳入的數據是否符合指定的規則,可以使用 class-validator 和 class-transformer 庫來實現驗證和轉換。
- ParseIntPipe(整數轉換管道):用于將傳入的字符串轉換為整數。
- ParseBoolPipe(布爾值轉換管道):用于將傳入的字符串轉換為布爾值。
- ParseArrayPipe(數組轉換管道):用于將傳入的字符串轉換為數組。
- ParseUUIDPipe(UUID 轉換管道):用于將傳入的字符串轉換為 UUID。
- DefaultValuePipe(默認值管道):用于在傳入的參數不存在時,給參數設置一個默認值。
- ParseEnumPipe(枚舉轉換管道):用于將傳入的字符串轉換為枚舉類型。
- ParseFloatPipe(浮點數轉換管道):用于將傳入的字符串轉換為浮點數。
- ParseFilePipe(文件轉換管道):用于將傳入的文件轉換為上傳的文件對象。
接下來我們測試一下內置 Pipe 的功能:
創建項目
nest new pipe -p npm
修改 app.controller.ts 可以看到這個接口默認接收test的字符串參數
import { Controller, Get, Query } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test') test: string): string {return test;}
}
1、ParseIntPipe
我們可以使用ParseIntPipe 將接收的字符串參數轉為整數:
import { Controller, Get, ParseIntPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test', ParseIntPipe) test: string): string {return test+10;}
}
訪問接口 http://localhost:3000/?test=100 可以看到參數test傳入 100 變成了 110
且當我們傳入的參數不能轉為init時 則會報錯 例如下面 訪問 http://localhost:3000/?test=ww
這個返回的報錯 我們也可以自定義 但是這種方式需要使用new XxxPipe 的方式 例如指定狀態碼為404
import { Controller, Get, HttpStatus, ParseIntPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test', new ParseIntPipe({errorHttpStatusCode: HttpStatus.NOT_FOUND,})) test: string): string {return test + 10;}
}
同時也可以拋出異常再進行處理
import { Controller, Get, HttpException, HttpStatus, ParseIntPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test', new ParseIntPipe({errorHttpStatusCode: HttpStatus.NOT_FOUND,exceptionFactory(error) {console.log(error);throw new HttpException('測試報錯' + error, HttpStatus.NOT_IMPLEMENTED)},})) test: string): string {return test + 10;}
}
2、ParseFloatPipe
ParseFloatPipe 的作用是將參數轉為float 類型
我們新建一個接口: test
import { Controller, Get, HttpException, HttpStatus, ParseFloatPipe, ParseIntPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test', new ParseIntPipe({errorHttpStatusCode: HttpStatus.NOT_FOUND,exceptionFactory(error) {console.log(error);throw new HttpException('測試報錯' + error, HttpStatus.NOT_IMPLEMENTED)},})) test: string): string {return test + 10;}@Get('test')getTest(@Query('test', ParseFloatPipe) test: number) {return test + 10;}
}
訪問 http://localhost:3000/test?test=10.4
同樣可以new ParseFloatPipe 的形式,傳入 errorHttpStatusCode 和 exceptionFactory
3、ParseBoolPipe
用于將傳入的字符串轉換為布爾值。
@Get('boolean')getBoolean(@Query('test') test: boolean) {return test;}
訪問 http://localhost:3000/boolean?test=false
4、ParseArrayPipe
用于將傳入的字符串轉換為數組。
@Get('array')getArray(@Query('test', ParseArrayPipe) test: number[]) {return test.reduce((pre, cur) => pre + cur, 0);}
保存代碼可以發現報錯了 提示需要class-validator 這個包class-class-class-validator 允許使用基于裝飾器和非裝飾器的驗證。 內部使用 validator.js 來執行驗證。
pnpm install class-validator
安裝之后啟動 發現還是報錯 缺少 class-transformer
class-transformer 允許您將普通對象轉換為類的某個實例,反之亦然。 此外,它還允許根據條件序列化/反序列化對象。 這個工具在前端和后端都非常有用。
pnpm install class-transformer
訪問 http://localhost:3000/array?test=1,2,3,4
可以發現 每一項都提取出來了但是類型還是string 沒有轉換成number類型
此時需要 new XxxPipe 的方式傳入參數:
@Get('array')getArray(@Query('test', new ParseArrayPipe({items: Number,})) test: number[]) {return test.reduce((pre, cur) => pre + cur, 0);}
再次訪問 http://localhost:3000/array?test=1,2,3,4
同時還可以指定傳入時的分割符: separator: ‘/’,
@Get('array')getArray(@Query('test', new ParseArrayPipe({items: Number,separator: '/',})) test: number[]) {return test.reduce((pre, cur) => pre + cur, 0);}
訪問 http://localhost:3000/array?test=1/2/3/4
當我們沒有傳入參數的時候會報錯:
我們可以通過設置 optional 來實現不傳參數不報錯
@Get('array')getArray(@Query('test', new ParseArrayPipe({items: Number,separator: '/',optional: true,})) test: number[]) {return test}
5、ParseEnumPipe
用于將傳入的字符串轉換為枚舉類型。
import { Controller, Get, HttpException, HttpStatus, ParseArrayPipe, ParseEnumPipe, ParseFloatPipe, ParseIntPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';enum TestEnum {A = 'A111',B = 'B111',
}@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test', new ParseIntPipe({errorHttpStatusCode: HttpStatus.NOT_FOUND,exceptionFactory(error) {console.log(error);throw new HttpException('測試報錯' + error, HttpStatus.NOT_IMPLEMENTED)},})) test: string): string {return test + 10;}@Get('test')getTest(@Query('test', ParseFloatPipe) test: number) {return test + 10;}@Get('boolean')getBoolean(@Query('test') test: boolean) {return test;}@Get('array')getArray(@Query('test', new ParseArrayPipe({items: Number,separator: '/',optional: true,})) test: number[]) {return test}@Get('enum/:test')getEnum(@Query('test', new ParseEnumPipe(TestEnum)) test: TestEnum) {return test}
}
訪問 http://localhost:3000/enum/111
當我們傳的參數不是枚舉定義的類型時會報錯
訪問 http://localhost:3000/enum/555
6、 ParseUUIDPipe
用于將傳入的字符串轉換為 UUID。在參數里,可以用 ParseUUIDPipe 來校驗是否是 UUID
首先我們安裝一下 uuid 用于生成uuid
pnpm install uuid
接著我們實現2個接口 getUuid getUuid2
import { Controller, Get, HttpException, HttpStatus, Param, ParseArrayPipe, ParseEnumPipe, ParseFloatPipe, ParseIntPipe, ParseUUIDPipe, Query } from '@nestjs/common';
import { AppService } from './app.service';const uuid = require('uuid');enum TestEnum {A = '111',B = '222',C = '333'
}@Controller()
export class AppController {constructor(private readonly appService: AppService) { }@Get()getHello(@Query('test', new ParseIntPipe({errorHttpStatusCode: HttpStatus.NOT_FOUND,exceptionFactory(error) {console.log(error);throw new HttpException('測試報錯' + error, HttpStatus.NOT_IMPLEMENTED)},})) test: string): string {return test + 10;}@Get('test')getTest(@Query('test', ParseFloatPipe) test: number) {return test + 10;}@Get('boolean')getBoolean(@Query('test') test: boolean) {return test;}@Get('array')getArray(@Query('test', new ParseArrayPipe({items: Number,separator: '/',optional: true,})) test: number[]) {return test}@Get('enum/:test')getEnum(@Param('test', new ParseEnumPipe(TestEnum)) e: TestEnum) {return e}@Get('uuid')getUuid() {return uuid.v4()}@Get('uuid/:uuid')getUuid2(@Param('uuid', new ParseUUIDPipe) uuid: string) {return uuid}
}
訪問 http://localhost:3000/uuid 獲取uuid
接著訪問 http://localhost:3000/uuid/0a5c5ce9-22ff-4091-85ef-523fcb64223c 可以看到正常訪問
但是如果參數不是正常的uuid那么會報錯
http://localhost:3000/uuid/xxx
7、DefaultValuePipe
用于在傳入的參數不存在時,給參數設置一個默認值。
創建一個接口:
@Get('default')getDefault(@Query('test', new DefaultValuePipe('test')) test: string) {return test}
當我們沒傳參數的時候 會使用默認值test http://localhost:3000/default
當我們傳參數之后將會返回參數 例如 http://localhost:3000/default?test=123456
8、自定義Pipe
首先創建一個 pipe:
nest g pipe www --flat --no-spec
www.pipe.ts:
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common';@Injectable()
export class WwwPipe implements PipeTransform {transform(value: any, metadata: ArgumentMetadata) {console.log(value,metadata);return 'www';}
}
增加接口:
@Get('www')getWww(@Query('test', WwwPipe) test: string, @Query('test2', WwwPipe) test2: string) {return test + test2}
瀏覽器訪問 http://localhost:3000/www?test=1234&test2=1
這就是Pipe返回的值
控制臺打印了 value 就是 query、param 的值,而 metadata 里包含 type、metatype、data
type 就是 @Query、@Param、@Body 裝飾器,或者自定義裝飾器
metatype 是參數的 ts 類型
data 參數值