自定义验证器验证对象键

问题描述

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

    public List<GrantedAuthority> getAuthorities(String token) {
    String[] claims = getClaimsFromToken(token);
    return StreamSupport.stream(claims).map(SimpleGrantedAuthority::new).collect(Collectors.toList());
}

错误参数示例:验证失败

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

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

我的代码

any-endpoint?filters={"blaBla"=["1","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

怎么做?

解决方法

好的,因此,如果您真的想以该格式发送查询,则可以使用@Transform()中的class-transformer装饰器,并使用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格式(我也将类分开,因为我更喜欢每个文件一个类)。使用上面的方法,传递给filters的值将从字符串值获取到JSON(纯文本),然后从纯文本获取到类。

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

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

现在您可以传递

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

它会在尝试传递时成功

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

它将失败。

,

还没有测试过,但是从docs看来,这就是您所需要的:

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