如何在NestJS装饰器中比较DTO内部字段并关联校验?
可以实现跨字段校验,但无法直接将id注入到字段装饰器中
字段装饰器(比如你定义的@MyCustomDecorator())是在类定义阶段执行的,此时无法获取到DTO实例的具体字段值,也没办法直接访问同一类中其他字段的实例数据。要实现你需要的「id大于10且hasPriority为true时拒绝请求」的校验逻辑,推荐用以下两种方案:
方案一:使用class-validator的类级自定义校验器
利用class-validator的类级校验器,可以拿到整个DTO实例,从而实现跨字段的关联校验:
- 定义自定义校验约束类
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments, Validate } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; @ValidatorConstraint({ name: 'idAndPriorityCheck', async: false }) export class IdAndPriorityCheck implements ValidatorConstraintInterface { // 接收整个DTO实例作为参数 validate(dto: MyDTO, args: ValidationArguments) { // 执行校验逻辑 if (dto.id > 10 && dto.hasPriority) { return false; // 返回false表示校验不通过 } return true; } // 校验不通过时的提示信息 defaultMessage(args: ValidationArguments) { return '当id大于10时,hasPriority不能设置为true'; } }
- 在DTO类上添加校验装饰器
@Validate(IdAndPriorityCheck) // 类级别校验器 export class MyDTO { @ApiProperty() id: number; // 注意TypeScript中没有integer类型,应该用number @ApiProperty() hasPriority: boolean; }
方案二:使用NestJS自定义管道
通过自定义管道,可以在请求数据绑定到DTO后,对整个DTO对象进行校验:
- 实现自定义管道
import { PipeTransform, Injectable, BadRequestException } from '@nestjs/common'; import { MyDTO } from './path/to/my-dto'; @Injectable() export class IdPriorityValidationPipe implements PipeTransform { transform(value: MyDTO) { if (value.id > 10 && value.hasPriority) { throw new BadRequestException('当id大于10时,hasPriority不能设置为true'); } return value; // 校验通过则返回原对象 } }
- 在控制器路由中使用管道
import { Controller, Post, Body } from '@nestjs/common'; import { MyDTO } from './path/to/my-dto'; import { IdPriorityValidationPipe } from './path/to/id-priority-pipe'; @Controller('example') export class ExampleController { @Post() create(@Body(new IdPriorityValidationPipe()) dto: MyDTO) { // 处理请求逻辑 return dto; } }
这两种方案都能满足你的跨字段校验需求,选择哪种取决于你的项目习惯:如果已经在使用class-validator做字段校验,方案一更统一;如果需要更灵活的请求处理逻辑,方案二更适合。
内容的提问来源于stack exchange,提问作者Diego Said Bechir
相关产品推荐
相关产品推荐

