请求主体中的布尔参数在NestJS API中始终为true

时间:2019-11-26 08:28:57

标签: typescript nestjs class-validator class-transformer

在我的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参数的请求正文包含名为laserMode的属性,该属性应为布尔类型,并且可以像 parameters DTO这样进行验证

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

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

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

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

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应用程序而不是邮递员时会注意到相同的结果。 所以!?

2 个答案:

答案 0 :(得分:5)

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

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

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;
}

答案 1 :(得分:1)

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

有一个issue请求更改class-transformer的行为。