You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Nest.js应用中对REST API的动态属性名Tag对象做校验

Nest.js class-validator 动态Tag属性校验实现方案

核心实现思路是通过class-validator提供的自定义校验装饰器能力,覆盖动态属性的规则校验,具体操作步骤如下:

步骤1:实现自定义校验装饰器

新建自定义装饰器,封装Tag对象的所有校验规则,同时兼容普通对象和Map两种Tag定义形式:

import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator';

export function IsValidTag(validationOptions?: ValidationOptions) {
  return function (target: Function) {
    registerDecorator({
      name: 'isValidTag',
      target: target,
      options: validationOptions,
      validator: {
        validate(value: any, args: ValidationArguments) {
          // 适配普通对象类型的Tag
          if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
            const keys = Object.keys(value);
            // 校验Tag仅含1个属性
            if (keys.length !== 1) return false;

            const key = keys[0];
            const val = value[key];
            // 校验键规则:长度1-255,不含:
            if (typeof key !== 'string' || key.length < 1 || key.length > 255 || !/^[^:]+$/.test(key)) {
              return false;
            }
            // 校验值规则:字符串,长度1-255
            if (typeof val !== 'string' || val.length < 1 || val.length > 255) {
              return false;
            }
            return true;
          }

          // 适配Map类型的Tag
          if (value instanceof Map) {
            if (value.size !== 1) return false;
            const [key, val] = value.entries().next().value;
            // 校验键规则
            if (typeof key !== 'string' || key.length < 1 || key.length > 255 || !/^[^:]+$/.test(key)) {
              return false;
            }
            // 校验值规则
            if (typeof val !== 'string' || val.length < 1 || val.length > 255) {
              return false;
            }
            return true;
          }

          return false;
        },
        defaultMessage(args: ValidationArguments) {
          return 'Tag对象不符合规则:仅能包含1个键值对,键长度为1-255且不能包含":",值为长度1-255的字符串';
        }
      }
    });
  };
}

步骤2:修饰Tag类和Payload DTO

2.1 修饰Tag类

直接给你定义的Tag类加自定义装饰器即可:

// 普通动态对象形式
@IsValidTag()
export class Tag {
  [key: string]: string;
}

// 或者Map继承形式
@IsValidTag()
export class Tag extends Map<string, string> {}

2.2 调整Payload DTO

注意要引入class-transformer的@Type装饰器,确保嵌套对象能被正确转换触发校验:

import { Type } from 'class-transformer';
import {
  ArrayMaxSize,
  ArrayMinSize,
  IsArray,
  ValidateNested
} from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';

export class Payload {
  // ...其他属性
  @IsArray()
  @ArrayMinSize(1)
  @ArrayMaxSize(11)
  @ValidateNested()
  @Type(() => Tag) // 替换你原来的@ValidateType,这是class-transformer的标准装饰器
  @ApiProperty()
  tags: Tag[];
}

步骤3:开启全局校验管道转换

在项目入口main.ts中配置全局ValidationPipe,开启transform配置,确保请求普通对象能被转换为DTO类实例触发校验:

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe({
    transform: true, // 必须开启,否则嵌套校验不生效
    // 其他可选配置,比如whitelist: true自动剔除未声明的属性
  }));
  await app.listen(3000);
}
bootstrap();

可选优化

如果需要更精细化的错误提示,可以在校验逻辑中记录错误类型,在defaultMessage中返回对应提示即可。

内容的提问来源于stack exchange,提问作者Serhii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 15:36:03