自定义验证器验证对象键

custom-validator validate object keys

我用打字稿项目构建了 nestjs,我正在尝试验证过滤器查询参数。 我只希望过滤键和值可以通过验证。 良好参数的示例:通过验证

any-endpoint?filters={"userIds"=["1","2","5"],"ages"=[25]}

any-endpoint?filters={"names"=["david","samuel"],"ages"=[21]}

错误参数示例:验证失败

any-endpoint?filters={"blaBla"=["1","2","5"],"ages"=[25]} // here the key blaBla not one of the filters options

any-endpoint?filters={"names"=[1,2]} // here the values of names is not string, it should be string

我的代码

import { IsNumber, IsOptional,IsArray, IsString } from 'class-validator';

class FiltersOptionsDto {
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  userIds?: string[];

  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  ages?: number[];

  @IsOptional()
  @IsArray()
  @IsNumber({}, { each: true })
  names?: string[];
}

export class AQueryDto {
  @IsOptional()
  // what to add here?
  filters?: FiltersOptionsDto;
}

怎么做?

还没有测试过,但是从 docs 我认为这就是你需要的:

export class AQueryDto {
  @IsOptional()
  @ValidateNested() // +
  filters?: FiltersOptionsDto;
}

好吧,所以如果你真的想以那种格式发送查询,你可以使用 class-transformer 中的 @Transform() 装饰器并使用 plainToClass 来转换过滤器值。不过,要做到这一点,您需要做一些事情。

  1. @ValidateNested() 装饰器是必要的,以确保它可以按预期进行验证。即可以验证子对象。

  2. 需要使用 @Transform() 装饰器。这对我有用

import { IsOptional, ValidateNested } from 'class-validator';
import { Transform, plainToClass } from 'class-transformer'
import { FiltersOptionsDto } from './filter.dto';

export class AQueryDto {
  @IsOptional()
  @ValidateNested()
  @Transform((value) =>  plainToClass(FiltersOptionsDto, JSON.parse(value.replace(/=/g, ':'))))
  filters?: FiltersOptionsDto;
}

每个 = 都需要制作成 : 以便它是正确的 JSON 格式(我也分开了 classes 因为我更喜欢一个class 每个文件)。通过以上,传入 filters 的值将从字符串值获取到 JSON(普通),然后从普通到 class.

  1. 您需要在 ValidationPipe 中设置 forbidNonWhitelisted: true。我是这样做的:
@Module({
  providers: [
    {
      provide: APP_PIPE,
      useValue: new ValidationPipe({ forbidNonWhitelisted: true })
    }
  ]
})
export class AppModule {}

(当然还有其他提供者和控制者)。我还想添加 transform: true 以便它不再是 JSON 或字符串,而是实际的 class.

现在可以传入了

?filters={"userIds"=["1","2","5"],"ages"=["25"]}

它会在尝试传入时成功

?filters={"blaBla"=["1","2","5"],"ages"=[25]}

它会失败。