6

在我的 API 中考虑这个端点:

@Post('/convert')
  @UseInterceptors(FileInterceptor('image'))
  convert(
    @UploadedFile() image: any,
    @Body(
      new ValidationPipe({
        validationError: {
          target: false,
        },
        // this is set to true so the validator will return a class-based payload
        transform: true,
        // this is set because the validator needs a tranformed payload into a class-based
        // object, otherwise nothing will be validated
        transformOptions: { enableImplicitConversion: true },
      }),
    )
    parameters: Parameters,
  ) {
    return this.converterService.start(image, parameters);
  }

设置为parameters参数的请求正文包含一个称为布尔类型的属性,它在参数 DTOlaserMode上像这样进行验证:

  @IsDefined()
  @IsBoolean()
  public laserMode: boolean;

现在奇怪的是,当从 PostMan 发送请求时:

  1. laserMode = false
  2. laserMode = cool(布尔值以外的字符串)

我注意到它laserMode总是设置为 true,这是在验证过程完成之后,因为当我console.log类的构造函数中的 Parameter 实例时

export class Parameters {
  ...
  constructor() {
    console.log('this :', this);
  }
  ...
}

没看到楼盘!

注意:当laserMode从请求中删除时,返回预期的验证错误(应该定义,应该是布尔值)。

// the logged instance 'this' in the constructor
this : Parameters {
  toolDiameter: 1,
  sensitivity: 0.95,
  scaleAxes: 200,
  deepStep: -1,
  whiteZ: 0,
  blackZ: -2,
  safeZ: 2,
  workFeedRate: 3000,
  idleFeedRate: 1200,
  laserPowerOn: 'M04',
  laserPowerOff: 'M05',
  invest: Invest { x: false, y: true }
}
// the logged laserMode value in the endpoint handler in the controller
parameters.laserMode in controller : true
// the logged laser value from the service
parameters.laserMode in service : true
  • 检查拼写错误
  • 使用 Vue 应用程序而不是邮递员时会注意到相同的结果。所以!!?
4

3 回答 3

11

这就是我在设法保持布尔类型的同时解决问题的方法。

通过键引用原始对象而不是使用解构后的值。

import { Transform } from 'class-transformer';

const ToBoolean = () => {
  const toPlain = Transform(
    ({ value }) => {
      return value;
    },
    {
      toPlainOnly: true,
    }
  );
  const toClass = (target: any, key: string) => {
    return Transform(
      ({ obj }) => {
        return valueToBoolean(obj[key]);
      },
      {
        toClassOnly: true,
      }
    )(target, key);
  };
  return function (target: any, key: string) {
    toPlain(target, key);
    toClass(target, key);
  };
};

const valueToBoolean = (value: any) => {
  if (value === null || value === undefined) {
    return undefined;
  }
  if (typeof value === 'boolean') {
    return value;
  }
  if (['true', 'on', 'yes', '1'].includes(value.toLowerCase())) {
    return true;
  }
  if (['false', 'off', 'no', '0'].includes(value.toLowerCase())) {
    return false;
  }
  return undefined;
};

export { ToBoolean };
export class SomeClass {
  @ToBoolean()
  isSomething : boolean;
}
于 2021-03-18T19:24:41.770 回答
8

这是由于选项enableImplicitConversion。显然,所有字符串值都被解释为true,甚至是字符串'false'

有一个问题要求更改class-transformer.

于 2019-11-26T09:02:41.660 回答
5

找到了解决类变压器问题的方法

你可以使用这个:

@IsBoolean()
@Transform(({ value} ) => value === 'true')
public laserMode: boolean;

这将根据字符串是否为“真”或任何其他字符串将字符串转换为布尔值。一个简单的解决方法,但每个字符串都与 true 不同,结果为 false。

于 2021-12-17T13:04:56.000 回答