實現nest的自定義註解

語言: CN / TW / HK

前言

Nest 與 class-validator 配合得很好,它允許我們使用基於裝飾器的驗證,在dto層中我們可以通過它的一些內置註解完成對參數的一些常用校驗。

但是,當我們在寫業務代碼時,內置註解往往不能滿足我們,此時我們為了代碼的一致性,就需要根據需求自定義一個註解出來,本文將帶着大家一起實現一個註解,歡迎各位感興趣的開發者閲讀本文。

場景概述

客户端傳入一個不符合規範的json字符串,我們需要對其進行截取後,再轉成json對象進行下一步的校驗,客户端傳入的字符串如下所示:

typescript var config = '{"name":"aa","age":"21","title":"標題測試"}'

在處理的時候,需要把var config =截取掉,只保留json字符串,然後轉成json對象,要求屬性總數必須大於2,我們很容易就能寫出代碼來,如下所示:

```typescript // 驗證配置字符串是否符合規範 export function verifyConfig( draftConfig?: string ): boolean | Record { // 去除多餘字符 if (draftConfig && draftConfig.length >= 12) { draftConfig = draftConfig.substring(12, draftConfig.length); } let draftData = {}; try { if (typeof draftConfig === "string") { draftData = JSON.parse(draftConfig); } // 草稿json字段不足 if (Object.keys(draftData).length < 2) { return false; } } catch (e) { // 草稿配置數據格式錯誤 return false; } return draftData; }

```

實現思路

本文繼續沿用文章“使用NestJS搭建服務端應用”所創建的項目,以此為基礎進行擴展。

我們在閲讀class-validator倉庫文檔的custom-validation-decorators章節後,大概瞭解了它的流程,接下來我們來實踐它。

註冊裝飾器

首先,我們在項目根錄下創建decorators文件夾,所有註解的實現文件都會放在此目錄下。隨後我們在其目錄下創建ConfigDecor.ts文件。

我們通過registerDecorator方法來註冊一個裝飾器,代碼如下所示:

  • IsConfig 為註解的名稱,它是函數類型,接受一個ValidationOptions類型的可選參數
  • 裝飾器註冊函數中有一個validator屬性,用於校驗數據,將在下個章節進行詳細講解

```typescript // 配置驗證註解 export function IsConfig(validationOptions?: ValidationOptions) { return function (object: Record, propertyName: string): void { // 註冊一個裝飾器 registerDecorator({ name: "IsConfig", target: object.constructor, options: validationOptions, propertyName: propertyName, validator: IsConfigConstraint }); }; }

```

數據校驗類

裝飾器的validator屬性值是一個用@ValidatorConstraint裝飾的一個類,這個類必須實現ValidatorConstraintInterface接口。其代碼如下所示:

  • validate 接受的參數就是dto中使用註解的字段所對應的值,我們需要的就是對它進行校驗,校驗函數就是用我們在文章開頭寫好的verifyConfig方法。
  • defaultMessage 就是驗證不通過時,默認返回給客户端的報錯信息

typescript // 配置驗證程序 @ValidatorConstraint({ async: true }) export class IsConfigConstraint implements ValidatorConstraintInterface { validate(value: string): Promise<boolean> | boolean { // 對草稿配置進行校驗 // 校驗程序返回值為boolean類型則代數據格式錯誤 return typeof verifyConfig(value) !== "boolean"; } // 驗證失敗時的默認錯誤信息 defaultMessage(args: ValidationArguments): string { return `property ${args.property} data format error`; } }

使用裝飾器

最後,我們只需要像使用內置裝飾器一樣使用它就可以了,代碼如下所示:

```typescript export class AppDto { @MinLength(5) @IsString() public id!: string; @IsString() public title!: string; @IsString() public name!: string; @IsConfig() public config!: string; }

```

最後,我們啟動項目,使用postman對其進行測試,如下圖所示:

  • 我們傳了一個不符合規範的字符串,裝飾器校驗不通過,返回了我們定義好的默認校驗信息。

image-20220217012646287

我們在來測試下正確數據的情況,如下圖所示,成功調用:

image-20220217012920927

小tip: 我們在註冊裝飾器時,提供了一個可選參數,它的作用就是為了其能像內置註解一樣,修改其公開屬性,例如message,我們可以對驗證失敗時的錯誤信息進行自定義。

image-20220217013237077

示例代碼

本文中所列舉的完整代碼請移步:

寫在最後

至此,文章就分享完畢了。

我是神奇的程序員,一位前端開發工程師。

如果你對我感興趣,請移步我的個人網站,進一步瞭解。

  • 文中如有錯誤,歡迎在評論區指正,如果這篇文章幫到了你,歡迎點贊和關注😊
  • 本文首發於神奇的程序員公眾號,未經許可禁止轉載💌