日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
實現(xiàn)Nest中參數(shù)的聯(lián)合類型校驗

場景概述

export class AppDto {
@ApiProperty({ example: "2022年4月20日修改", description: "備注" })
@IsString()
@IsArray()
@ValidateNested({ each: true })
@Type(() => TextObjDto)
public text!: string | Array;
}

TextObjDto的代碼如下所示:

創(chuàng)新互聯(lián)服務(wù)項目包括武平網(wǎng)站建設(shè)、武平網(wǎng)站制作、武平網(wǎng)頁制作以及武平網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,武平網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到武平省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

export class TextObjDto {
@ApiProperty({ example: "修復(fù)了一些bug", description: "內(nèi)容" })
@IsString()
content!: string;
@ApiProperty({ example: "2022-04-20 07:52", description: "創(chuàng)建時間" })
@IsString()
createTime?: string;
@ApiProperty({ example: true, description: "是否為新功能標(biāo)識" })
@IsBoolean()
mark?: boolean;
}

啟動項目,用postman測試后發(fā)現(xiàn)并不好使,傳了array類型的數(shù)據(jù)又要求是string類型,傳了string類型的數(shù)據(jù)又要求是array類型。

注意:嵌套類型的對象驗證需要使用@ValidateNested和@Type注解, @Type接受一個回調(diào)函數(shù),函數(shù)內(nèi)部需要返回一個用class聲明的dto類。

解決方案

經(jīng)過一番求助,翻了一圈class-validator的文檔,發(fā)現(xiàn)沒有現(xiàn)成的解決方案。那么,就只能自己拿到參數(shù)搞自定義校驗了。

在class-transformer這個庫中,提供了Transform方法,它接受一個回調(diào)函數(shù)作為參數(shù),回調(diào)函數(shù)中提供了一個TransformFnParams類型的參數(shù),其中的value字段就是客戶端傳過來的參數(shù),我們只需要對其進行校驗即可。

接下來,我們來看下實現(xiàn)代碼,如下所示:

export class AppDto {
@ApiProperty({ example: "2022年4月20日修改", description: "備注" })
@IsOptional()
@Transform(({ value }) => checkTitleKey(value))
public text!: string | Array;
}

上述代碼中,我們有一個名為checkTitleKey的校驗函數(shù),因為需要自己校驗,所以就需要自己把TS的類型校驗復(fù)刻一遍出來,實現(xiàn)代碼如下所示:

  • 如果校驗通過直接返回value參數(shù)即可
  • 如果校驗不通過直接使用nest內(nèi)置異常進行拋出即可
export function checkTitleKey(
value: string | number | Array | undefined | null
): any {
if (typeof value === "string") {
// 不做更改,直接返回
return value;
} else if (value instanceof Array) {
// 不能為空數(shù)組
if (value.length <= 0) {
throw new BadRequestException(
"property text cannot be an empty array",
"Bad Request"
);
}
for (let i = 0; i < value.length; i++) {
// 校驗數(shù)組中的對象字段
const objKeys = Object.keys(value[i]);
if (objKeys.length <= 0) {
throw new BadRequestException(
"property text contains empty objects",
"Bad Request"
);
}
// 必須包含content字段
if (!objKeys.includes("content")) {
throw new BadRequestException(
"property text objects in the array must contain 'content'",
"Bad Request"
);
}
// 對每個key進行校驗
for (let j = 0; j < objKeys.length; j++) {
switch (objKeys[j]) {
case "content":
// content字段必須為string類型
if (typeof value[i].content !== "string") {
throw new BadRequestException(
"property text 'content' of the objects in the array must be of type string",
"Bad Request"
);
}
break;
case "duration":
if (typeof value[i].createTime !== "string") {
throw new BadRequestException(
"property text 'createTime' of the objects in the array must be of type number",
"Bad Request"
);
}
break;
case "delay":
if (typeof value[i].mark !== "boolean") {
throw new BadRequestException(
"property text 'mark' of the objects in the array must be of type number",
"Bad Request"
);
}
break;
default:
break;
}
}
}
return value;
} else {
throw new BadRequestException(
"text must be an array or string",
"Bad Request"
);
}
}

TextObjType的聲明也需要進行相對應(yīng)的修改,如下所示:

  • 全部變?yōu)榭蛇x參數(shù),參數(shù)的必傳與否已經(jīng)在校驗函數(shù)中處理了
  • 類型全部變?yōu)閍ny
export type TextObjType = {
content?: any;
createTime?: any;
mark?: any;
};

有一部分開發(fā)者可能比較迷惑,不是說ts用any是可恥行為嗎,這我就要糾正下你了,既然它存在自然有使用場景。在我這個場景中,對象里所有key的類型校驗都手動處理了,如果在此處定義了它的類型,在校驗函數(shù)中就會報黃色警告,因此針對于需要手動校驗類型的場景而言,使用any是最合適的。

結(jié)果校驗

最后,我們針對于代碼里定義的異常規(guī)則來驗證下其是否能正常工作,如下所示:

# text字段為string類型
{
"id":"122211",
"title":"新的標(biāo)題",
"text":"新替換的文本內(nèi)容",
"name":"新的名字",
"config":"var config = {\"name\":\"aa\",\"age\":\"21\",\"title\":\"標(biāo)題測試\"}"
}
>>> 接口調(diào)用成功

# text字段為Array類型所有key都存在
{
"id":"122211",
"title":"新的標(biāo)題",
"text":[{"content":"新文本","createTime":"2022-04-20","mark":false}],
"name":"新的名字",
"config":"var config = {\"name\":\"aa\",\"age\":\"21\",\"title\":\"標(biāo)題測試\"}"
}

>>> 接口調(diào)用成功

# text字段缺少content
{
"id":"122211",
"title":"新的標(biāo)題",
"text":[{"createTime":"2022-04-20","mark":false}],
"name":"新的名字",
"config":"var config = {\"name\":\"aa\",\"age\":\"21\",\"title\":\"標(biāo)題測試\"}"
}
>>> 接口報錯400:property text objects in the array must contain 'content'

# text字段為number類型
{
"id":"122211",
"title":"新的標(biāo)題",
"text":19,
"name":"新的名字",
"config":"var config = {\"name\":\"aa\",\"age\":\"21\",\"title\":\"標(biāo)題測試\"}"
}
>>> 接口報錯400:text must be an array or string

# text字段缺少createTime與mark
{
"id":"122211",
"title":"新的標(biāo)題",
"text":[{"content":"新文本"}],
"name":"新的名字",
"config":"var config = {\"name\":\"aa\",\"age\":\"21\",\"title\":\"標(biāo)題測試\"}"
}
>>> 接口調(diào)用成功

如下圖所示,我們列舉一個text字段為數(shù)字時的報錯截圖,運行結(jié)果符合預(yù)期,文章開頭的問題成功解決:


本文標(biāo)題:實現(xiàn)Nest中參數(shù)的聯(lián)合類型校驗
文章網(wǎng)址:http://www.dlmjj.cn/article/djhhcco.html