Nest 自定义注解实战教程
2023-12-24 07:55:02
使用 Nest 和 class-validator进行参数校验是前不久刚接触到一个新东西,很有意思,而且在业务中很常用,就打算写一篇自定义注解的文章来总结一下自己的心得,文中代码基于 Nest 和 class-validator,如果还没用过小伙伴可以去官网瞅瞅,这里就不多介绍了。
前言
Nest 与 class-validator 配合得很好,它允许我们使用基于装饰器的验证,在dto层中我们可以通过它的一些内置注解完成对参数的一些常用校验。
但是,当我们在写业务代码时,肯定还会遇到一些特殊需求的校验,此时我们需要自己去扩展 class-validator 的能力,来实现我们自己的校验逻辑。下面就来讲一讲如何自定义一个注解并使用它。
一、创建自定义注解
首先,我们需要创建一个新的装饰器,它将用于验证我们的参数。这个装饰器可以放在任何地方,但通常情况下,我们将其放在一个单独的文件中。
import { registerDecorator, ValidationOptions } from "class-validator";
export function IsPositiveNumber(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: "isPositiveNumber",
target: object.constructor,
propertyName: propertyName,
constraints: [],
options: validationOptions,
validator: {
validate(value: any) {
return typeof value === "number" && value > 0;
},
defaultMessage: "The value must be a positive number",
},
});
};
}
这个装饰器接收一个可选的验证选项对象,该对象可以用于配置验证器。在上面的例子中,我们使用了 registerDecorator()
函数来注册我们的装饰器。
第一个参数是装饰器的元数据对象,它指定了装饰器的一些属性,如名称、目标类、属性名和验证器。
第二个参数是装饰器函数,它接收两个参数:要验证的对象和属性名。
在装饰器函数中,我们使用 registerDecorator()
函数来注册验证器。验证器包含以下属性:
- 名称:验证器的名称。
- 目标:验证器的目标类。
- 属性名:验证器的属性名。
- 约束:验证器的约束。
- 选项:验证器的选项。
- 验证器:验证器的验证器函数。
二、使用自定义注解
现在我们已经创建了自定义注解,我们可以使用它来验证我们的参数。
import { IsPositiveNumber } from "./is-positive-number.decorator";
import { Body, Controller, Post } from "@nestjs/common";
@Controller()
export class AppController {
@Post()
create(@Body() body: CreateDto) {
// ...
}
}
class CreateDto {
@IsPositiveNumber()
age: number;
}
在这个例子中,我们使用 @IsPositiveNumber()
装饰器来验证 age
属性。如果 age
的值不是一个正数,那么验证器将返回一个错误。
三、自定义注解的扩展
除了上面介绍的简单示例之外,我们还可以通过扩展 ValidationArguments
类来创建更复杂的自定义注解。
import { registerDecorator, ValidationArguments, ValidationOptions } from "class-validator";
export function IsPositiveNumber(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: "isPositiveNumber",
target: object.constructor,
propertyName: propertyName,
constraints: [],
options: validationOptions,
validator: {
validate(value: any, args: ValidationArguments) {
const [relatedPropertyName] = args.constraints;
const relatedValue = args.object[relatedPropertyName];
return typeof value === "number" && value > 0 && value < relatedValue;
},
defaultMessage: "The value must be a positive number and less than related property value",
},
});
};
}
在这个例子中,我们使用 ValidationArguments
类来获取相关属性的值。然后,我们使用这些值来验证 age
的值。
总结
自定义注解是一种强大的工具,它允许我们对参数进行更复杂的验证。通过扩展 ValidationArguments
类,我们可以创建更灵活的自定义注解。
我希望这篇教程能帮助你了解如何使用 Nest 和 class-validator 来创建自定义注解。