成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

實(shí)現(xiàn)Nest中參數(shù)的聯(lián)合類(lèi)型校驗(yàn)

開(kāi)發(fā)
在nest的dto層對(duì)參數(shù)進(jìn)行校驗(yàn)時(shí),某個(gè)參數(shù)可能有多種類(lèi)型,遇到這種情況你會(huì)怎么處理?本文將跟大家分享這個(gè)問(wèn)題的解決方案。

場(chǎng)景概述

我們?cè)谶M(jìn)行接口開(kāi)發(fā)時(shí),客戶(hù)端需要傳入一個(gè)名為text的字段,它可能是string類(lèi)型或Array<Object>類(lèi)型(在TS中我們把這種關(guān)系稱(chēng)之為 聯(lián)合類(lèi)型 ),class-validator庫(kù)中提供了相關(guān)的校驗(yàn)注解,那把他們寫(xiě)在一起能否完成相關(guān)的校驗(yàn)?zāi)?,如下所示?/p>

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

TextObjDto的代碼如下所示:

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

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

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

解決方案

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

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

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

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

上述代碼中,我們有一個(gè)名為checkTitleKey的校驗(yàn)函數(shù),因?yàn)樾枰约盒r?yàn),所以就需要自己把TS的類(lèi)型校驗(yàn)復(fù)刻一遍出來(lái),實(shí)現(xiàn)代碼如下所示:

  • 如果校驗(yàn)通過(guò)直接返回value參數(shù)即可
  • 如果校驗(yàn)不通過(guò)直接使用nest內(nèi)置異常進(jìn)行拋出即可
export function checkTitleKey(
value: string | number | Array<TextObjType> | 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++) {
// 校驗(yàn)數(shù)組中的對(duì)象字段
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"
);
}
// 對(duì)每個(gè)key進(jìn)行校驗(yàn)
for (let j = 0; j < objKeys.length; j++) {
switch (objKeys[j]) {
case "content":
// content字段必須為string類(lèi)型
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的聲明也需要進(jìn)行相對(duì)應(yīng)的修改,如下所示:

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

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

結(jié)果校驗(yàn)

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

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

# text字段為Array類(lèi)型所有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)題測(cè)試\"}"
}

>>> 接口調(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)題測(cè)試\"}"
}
>>> 接口報(bào)錯(cuò)400:property text objects in the array must contain 'content'

# text字段為number類(lèi)型
{
"id":"122211",
"title":"新的標(biāo)題",
"text":19,
"name":"新的名字",
"config":"var config = {\"name\":\"aa\",\"age\":\"21\",\"title\":\"標(biāo)題測(cè)試\"}"
}
>>> 接口報(bào)錯(cuò)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)題測(cè)試\"}"
}
>>> 接口調(diào)用成功

如下圖所示,我們列舉一個(gè)text字段為數(shù)字時(shí)的報(bào)錯(cuò)截圖,運(yùn)行結(jié)果符合預(yù)期,文章開(kāi)頭的問(wèn)題成功解決:

責(zé)任編輯:趙寧寧 來(lái)源: 神奇的程序員
相關(guān)推薦

2024-06-19 10:04:15

ifC#代碼

2021-08-12 10:32:50

Spring Boot參數(shù)校驗(yàn)分組校驗(yàn)

2021-08-10 15:11:27

Spring Boot參數(shù)校驗(yàn)

2025-05-27 07:07:29

2022-03-18 21:51:10

Nest.jsAOP 架構(gòu)后端

2022-04-11 08:42:09

TypeScript子類(lèi)型定義

2022-07-27 22:59:53

Node.jsNest

2022-02-17 07:10:39

Nest自定義注解

2025-05-21 08:15:00

GoAPI開(kāi)發(fā)

2022-04-06 10:06:37

判斷算法數(shù)值校驗(yàn)

2025-05-14 00:00:00

2023-03-16 08:23:33

2022-12-30 08:49:41

SpringBoot@Validated

2021-12-22 06:56:06

MySQCrudjs

2012-02-21 14:04:15

Java

2022-06-30 07:45:29

搜索聯(lián)合搜索索引

2011-06-11 22:09:06

NET聯(lián)合體

2011-07-12 09:18:50

.NET

2022-02-02 20:21:24

短信驗(yàn)證碼登錄

2023-11-29 07:23:04

參數(shù)springboto
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人区精品一区二区婷婷 | 免费看的av| 一区二区三区在线播放 | 亚洲精品久久久久久首妖 | 超级乱淫av片免费播放 | 国产精品视频在线播放 | 黄色网址在线免费观看 | 亚洲电影一区二区三区 | 国产精品久久久久久久7电影 | 日韩精品免费 | 91精品无人区卡一卡二卡三 | 亚洲一区二区三区高清 | 亚洲成人福利 | 亚洲国产小视频 | 97色在线视频| 久久久久久国产精品免费免费男同 | 81精品国产乱码久久久久久 | 国产精品久久久久久久久久久久 | 天天av网| 日韩欧美在线观看视频 | 欧美9999| 国产精品毛片 | 久久一区二区精品 | 亚洲少妇综合网 | 欧美一区二区三区一在线观看 | 久久久久久久久国产成人免费 | 久久99久久| 国产精品视频偷伦精品视频 | 成人免费一区二区三区视频网站 | 午夜影院在线观看 | 国产午夜久久 | 国产精品自拍视频网站 | 男女午夜激情视频 | 免费国产一区 | 51ⅴ精品国产91久久久久久 | 国产精品免费在线 | 国产精品无| 国产精品久久久久久久久久99 | 成人免费毛片片v | 午夜精品一区 | 波多野结衣一区二区三区在线观看 |