前言
Nest 与 class-validator[1] 配合得很好,它允许我们使用基于装饰器的验证,在dto层中我们可以通过它的一些内置注解完成对参数的一些常用校验。
但是,当我们在写业务代码时,内置注解往往不能满足我们,此时我们为了代码的一致性,就需要根据需求自定义一个注解出来,本文将带着大家一起实现一个注解,欢迎各位感兴趣的开发者阅读本文。
场景概述
客户端传入一个不符合规范的json字符串,我们需要对其进行截取后,再转成json对象进行下一步的校验,客户端传入的字符串如下所示:
var config = '{"name":"aa","age":"21","title":"标题测试"}'
在处理的时候,需要把var config =
截取掉,只保留json字符串,然后转成json对象,要求属性总数必须大于2,我们很容易就能写出代码来,如下所示:
// 验证配置字符串是否符合规范 export function verifyConfig( draftConfig?: string ): boolean | Record<string, any> { // 去除多余字符 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搭建服务端应用[2]”所创建的项目,以此为基础进行扩展。
我们在阅读class-validator仓库文档的custom-validation-decorators[3]章节后,大概了解了它的流程,接下来我们来实践它。
注册装饰器
首先,我们在项目根录下创建decorators
文件夹,所有注解的实现文件都会放在此目录下。随后我们在其目录下创建ConfigDecor.ts
文件。
我们通过registerDecorator
方法来注册一个装饰器,代码如下所示:
- IsConfig 为注解的名称,它是函数类型,接受一个ValidationOptions类型的可选参数
- 装饰器注册函数中有一个validator属性,用于校验数据,将在下个章节进行详细讲解
// 配置验证注解 export function IsConfig(validationOptions?: ValidationOptions) { return function (object: Record<string, any>, propertyName: string): void { // 注册一个装饰器 registerDecorator({ name: "IsConfig", target: object.constructor, options: validationOptions, propertyName: propertyName, validator: IsConfigConstraint }); }; }
数据校验类
装饰器的validator
属性值是一个用@ValidatorConstraint
装饰的一个类,这个类必须实现ValidatorConstraintInterface
接口。其代码如下所示:
- validate 接受的参数就是dto中使用注解的字段所对应的值,我们需要的就是对它进行校验,校验函数就是用我们在文章开头写好的
verifyConfig
方法。 - defaultMessage 就是验证不通过时,默认返回给客户端的报错信息
// 配置验证程序 @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`; } }
使用装饰器
最后,我们只需要像使用内置装饰器一样使用它就可以了,代码如下所示:
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
示例代码
本文中所列举的完整代码请移步:
- JsonDataVerifyUtilas.ts[4]
- ConfigDecor.ts[5]
- AppDto[6]
写在最后
至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站[7],进一步了解。
- 公众号无法外链,如果文中有链接,可点击下方阅读原文查看😊