NestJS DTO校验:如何确保请求至少传入一个属性?
解决DTO空对象校验问题
要实现“请求至少传入一个属性”的校验,你可以通过自定义class-validator校验器来实现,具体步骤如下:
1. 创建自定义校验器
定义一个校验器类,用于检查DTO实例是否至少包含一个非未定义的属性:
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator'; @ValidatorConstraint({ name: 'atLeastOneField', async: false }) export class AtLeastOneFieldValidator implements ValidatorConstraintInterface { validate(obj: Record<string, any>, args: ValidationArguments) { // 遍历对象属性,判断是否存在至少一个非undefined的属性 return Object.values(obj).some(value => value !== undefined); } defaultMessage(args: ValidationArguments) { return '请求体至少需要传入一个有效属性'; } }
2. 在DTO类上应用校验器
修改你的WorkspaceDto,在类级别添加@Validate装饰器引入自定义校验器:
// import libs import { Validate } from 'class-validator'; import { AtLeastOneFieldValidator } from './path-to-your-validator'; // 替换为实际文件路径 export class WorkspaceDto { @Validate(AtLeastOneFieldValidator) // 类级别校验,强制至少传一个属性 @IsString() @IsNotEmpty() @Transform(({ value }) => value?.trim()) @ApiProperty() @IsOptional() id?: string; @IsString() @IsNotEmpty() @Transform(({ value }) => value?.trim()) @ApiProperty() @IsOptional() name?: string; @IsNotEmpty() @IsString() @Transform(({ value }) => value?.trim()) @ApiProperty() @IsOptional() domain?: string; @IsNotEmpty() @IsString() @Transform(({ value }) => value?.trim()) @IsOptional() @ApiProperty({ enum: WorkspaceStatusEnum, required: false }) @IsEnum(WorkspaceStatusEnum) status?: WorkspaceStatusEnum; }
逻辑说明
- 保留每个字段的
@IsOptional,允许单个字段可选,但类级别校验会强制要求至少有一个字段被传入。 - 当用户传入空对象
{}时,自定义校验器会返回false,触发错误提示拦截请求。 - 单个字段的
@IsNotEmpty等校验依然生效,确保传入的字段值符合格式要求。
内容的提问来源于stack exchange,提问作者green_dino
相关产品推荐
相关产品推荐

