如何在 nest.js 应用程序的 REST API 上验证动态 属性-name?

How to validate dynamic property-name on REST API in nest.js app?

任务是在管理 nest.js 应用程序之前验证有效负载。 每个负载可以包含 tag 个对象 (1 - 11)。 每个tag object只能有一个属性和值(属性由请求决定)

应验证标记对象:

任务看起来很简单。但我不知道如何验证 Tag 对象中动态构造的属性。

DTO 是(使用 class-validator 配置的验证):

import {
  ArrayMaxSize,
  ArrayMinSize,
  IsArray,
  IsDefined,
  IsNotEmpty,
  IsObject,
  IsString,
  Matches,
  MinLength,
  ValidateNested
} from 'class-validator';


export class Payload {
...
  @IsArray()
  @ArrayMinSize(1)
  @ArrayMaxSize(11)
  @ValidateType(() => Tag)
  @ValidateNested()
  @ApiProperty()
  tags: Tag[];
}

为了使 Tag 灵活(因为未知 属性 名称)它使 Map 扩展

export class Tag extends Map<string, string>{
}

或单个字段对象

export class Tag {
  [key: string]: string;
}

如何管理每个 Tag 所需的验证?

(排除带有 : 的输入的正则表达式是 /^[^:]+$/,应该应用于 key

我有解决方案,但比解决方案实施比较可能的方法更好。

1 个场景 是在 tags 字段

上放置额外的自定义验证装饰器
  @IsPropertyNameLength(1, 250,{ each: true })
  @IsPropertyNameMatches(/^[^:]+$/,{ each: true })
  @IsPropertyNameString({ each: true })
  @IsKeyNameLength(1, 250,{ each: true })
  @IsKeyNameMatches(/\w+|\d+/,{ each: true })
  @IsKeyNameString({ each: true })
  tags: Tag[];

这可能是个不错的解决方案。按照这种方式,我们会意识到装饰器名称没有带来足够的信息。为了使它们更通用,我们可以添加更多参数。但是这种改进不能改变我们验证的不是当前级别或下一级 属性 的事实。我们在下一个级别(tags[] -> Tag -> theProperty)之后对 属性 进行验证。

2个场景 是管理中间件层的验证。如果你想让报告具有相同的格式并遵循 class-validator 中提供的类似流程,这可能会带来一些困难,但好处是我们可以在构建更复杂的验证树的不同方法上进行验证。也方便测试。

3个场景 是拒绝动态 属性 名称(如果可能的话)并考虑开发替代模型,例如

export class Tag {
  key: string;
  value: string;
}

它让我们有机会使用 class-validator 提供的装饰器来满足我们的需要,例如

export class Tag {
  @Length(1, 250)
  @Matches(/^[^:]+$/)
  key: string;
  @Length(1, 250)
  @Matches(/\w+|\d+/)
  value: string;
}

P.S.

我已经按照第三种方式管理了我的解决方案。