我试图使用类验证器来验证传入的数据.数据由对象数组组成.应验证每个对象.

我面临的问题是,当所有内容都正确输入时,我会不断出错.似乎父类正在使用其子类的属性进行判断,因此子类的每个属性都会抛出whitelistValidation个错误.

这是正在生成的错误:

[
   {
      "target":{
         "drainPoints":[
            {
               "drainPointType":"roundsurface",
               "flowType":"normal",
               "flowCoefficient":0.5,
               "point":{
                  "x":0,
                  "y":0
               }
            }
         ]
      },
      "value":[
         {
            "drainPointType":"roundsurface",
            "flowType":"normal",
            "flowCoefficient":0.5,
            "point":{
               "x":0,
               "y":0
            }
         }
      ],
      "property":"drainPoints",
      "children":[
         {
            "target":[
               {
                  "drainPointType":"roundsurface",
                  "flowType":"normal",
                  "flowCoefficient":0.5,
                  "point":{
                     "x":0,
                     "y":0
                  }
               }
            ],
            "value":{
               "drainPointType":"roundsurface",
               "flowType":"normal",
               "flowCoefficient":0.5,
               "point":{
                  "x":0,
                  "y":0
               }
            },
            "property":"0",
            "children":[
               {
                  "target":{
                     "drainPointType":"roundsurface",
                     "flowType":"normal",
                     "flowCoefficient":0.5,
                     "point":{
                        "x":0,
                        "y":0
                     }
                  },
                  "value":"roundsurface",
                  "property":"drainPointType",
                  "constraints":{
                     "whitelistValidation":"property drainPointType should not exist"
                  }
               },
               {
                  "target":{
                     "drainPointType":"roundsurface",
                     "flowType":"normal",
                     "flowCoefficient":0.5,
                     "point":{
                        "x":0,
                        "y":0
                     }
                  },
                  "value":"normal",
                  "property":"flowType",
                  "constraints":{
                     "whitelistValidation":"property flowType should not exist"
                  }
               },
               {
                  "target":{
                     "drainPointType":"roundsurface",
                     "flowType":"normal",
                     "flowCoefficient":0.5,
                     "point":{
                        "x":0,
                        "y":0
                     }
                  },
                  "value":0.5,
                  "property":"flowCoefficient",
                  "constraints":{
                     "whitelistValidation":"property flowCoefficient should not exist"
                  }
               },
               {
                  "target":{
                     "drainPointType":"roundsurface",
                     "flowType":"normal",
                     "flowCoefficient":0.5,
                     "point":{
                        "x":0,
                        "y":0
                     }
                  },
                  "value":{
                     "x":0,
                     "y":0
                  },
                  "property":"point",
                  "constraints":{
                     "whitelistValidation":"property point should not exist"
                  }
               }
            ]
         }
      ]
   }
]

包含数组的DTO对象:

export class CreateDrainPointDTO extends DTO {
  @IsArray()
  @IsNotEmpty()
  @ArrayMinSize(1)
  @ValidateNested({ each: true })
  @Type(() => DrainPointDTO)
    drainPoints: DrainPoint[]
}

对象本身:

export class DrainPointDTO {
  @IsString()
  @IsOptional()
    uuid: string

  @IsEnum(DrainPointType)
  @IsNotEmpty()
    drainPointType: DrainPointType

  @IsEnum(DrainPointflowType)
  @IsNotEmpty()
    flowType: DrainPointflowType

  @IsArray()
  @IsNotEmpty()
   point: Point

  @IsNumber()
  @IsOptional()
    flowCoefficient: number
}

我的自定义DTO抽象类:

export abstract class DTO {
  static async factory<T extends DTO>(Class: new () => T, partial: Partial<T>): Promise<T> {
    const dto = Object.assign(new Class(), partial)

    const errors = await validate(dto, { whitelist: true, forbidNonWhitelisted: true })

    if (errors.length > 0) {
      throw new CustomError()
        .withError('invalid_parameters')
        .withValidationErrors(errors)
    }

    return dto
  }
}

我使用这个DTO抽象类是为了有一种干净的方法来判断控制器内部的主体:

  async createDrainPoint (req: Request, res: Response): Promise<void> {
    const dto = await DTO.factory(CreateDrainPointDTO, req.body as Partial<CreateDrainPointDTO>)

    const drainPoints = await this.drainPointService.create(dto)

    res.status(201).json(DrainPointTransformer.array(drainPoints))
  }

推荐答案

问题是,创建数据的方式实际上并不是以数组中的DrainPointDTO个实例结束,而仅仅是符合其形状的对象.您可以通过以下内容看到这一点:

async createDrainPoint (req: Request, res: Response): Promise<void> {
  const dto = await DTO.factory(CreateDrainPointDTO, req.body as Partial<CreateDrainPointDTO>)

  console.log(dto.drainPoints[0].constructor);

它将输出[Function: Object],而不是[class DrainPoint].

您正在创建一个CreateDrainPointDTO的实例,Object.assign正在填充值,但它不会将任何嵌套值映射到类实例.其功能等同于:

const dto = new CreateDrainPointDTO()

dto.drainPoints = [
  {
    uuid: 'some-id',
    drainPointType: DrainPointType.roundsurface,
    flowType: DrainPointflowType.normal,
    flowCoefficient: 0.5,
    point: {
      x: 0,
      y: 0,
    },
  },
]

// outputs '[Function: Object]', NOT '[class DrainPoint]'
console.log(dto.drainPoints[0].constructor)

由于所有的decorator都是DrainPointDTO类的一部分,所以它不知道如何验证它.class-validator通常与class-transformer结合使用(我假设您已经有了它,因为Typedecorator 就是从这里来的).它将创建嵌套类的实例(只要它们在@Type中指定类,您已经这样做了).对于您的工厂,您可以执行以下操作:

import { plainToInstance } from 'class-transformer';

// ...
const dto = plainToInstance(Class, partial);

注意:您可能不希望工厂接受Partial<T>,而希望工厂只接受T.如果用于初始化类的值缺少任何必需的值,那么它无论如何都将无效.对于req.body来说,这并不重要,因为它的类型是any,但如果您使用它以编程方式创建一个,它将为您提供缺少字段的静态判断.

Javascript相关问答推荐

空的结果抓取网站与Fetch和Cheerio

从Node JS将对象数组中的数据插入Postgres表

JS,当你点击卡片下方的绿色空间,而它是在它的背后转动时,

S文本内容和值不必要的不同

从包含数百行的表中获取更改后的值(以表单形式发送到后端)的正确方法是什么?

编辑文本无响应.onClick(扩展脚本)

提交链接到AJAX数据结果的表单

正则表达式,允许我匹配除已定义的子字符串之外的所有内容

在Java中寻找三次Bezier曲线上的点及其Angular

禁用.js文件扩展名并从目录导入隐式根index.js时,找不到NodeJS导入模块

更新动态数据中对象或数组中的所有值字符串

覆盖加载器页面避免对页面上的元素进行操作

有效路径同时显示有效路径组件和不存在的路径组件

第一项杀死下一项,直到数组长度在javascript中等于1

自动滚动功能在当前图像左侧显示上一张图像的一部分

是否设置以JavaScript为背景的画布元素?

设置复选框根据选中状态输入选中值

当触发AJAX POST请求时,绕过对PHP生成的表的加载函数

try 使用Reaction路由V5渲染多个布局

更改垫子树界面线条边框底部问题的方向设计Angular