请求正文中的布尔参数在 NestJS api 中始终为真
Posted
技术标签:
【中文标题】请求正文中的布尔参数在 NestJS api 中始终为真【英文标题】:Boolean parameter in request body is always true in NestJS api 【发布时间】:2020-03-21 14:50:16 【问题描述】:在我的 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 发送请求时:
laserMode = false
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 应用程序而不是邮递员时会发现相同的结果。
所以!!?
【问题讨论】:
【参考方案1】:这就是我在设法保持布尔类型的同时解决问题的方法。
通过键引用原始对象而不是使用解构值。
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;
【讨论】:
不确定您使用的是哪个版本的Transform
,我不得不将其稍微更改为: const toPlain = Transform( (value) => return value; , toPlainOnly: true, ); const toClass = (target: any, key: string) => return Transform( (value) => return valueToBoolean(value); , toClassOnly: true, )(target, key); ;返回函数(目标:任意,键:字符串) toPlain(目标,键); toClass(目标,键); ; ;
你们用的是什么版本?我在 v0.4.0 上。你试过FoosMaster的建议吗?您的版本转换功能的文档应该让您知道您可以访问什么。就我而言,我确实可以访问原始对象和对象中的属性,这就是它起作用的原因。您可以使用 obj[key] 引用该值
github.com/typestack/class-transformer#advanced-usage【参考方案2】:
这是由于选项enableImplicitConversion
。显然,所有字符串值都被解释为true
,甚至字符串'false'
。
有一个issue 请求更改class-transformer
的行为。
【讨论】:
好的,但没有它,所有 DTO 属性规则的验证都会失败。我应该转换为字符串而不是布尔值吗? 您可以改用@Transform
注释来控制转换,参见例如***.com/a/55480830/4694994
感谢您的回答,但我将属性转换为字符串而不是布尔值,从而避免了很多麻烦。【参考方案3】:
找到了解决类转换器问题的解决方法
你可以用这个:
@IsBoolean()
@Transform(( value ) => value === 'true')
public laserMode: boolean;
这会将字符串转换为布尔值,基于它是“真”还是任何其他字符串。一个简单的解决方法,但每个字符串都与 true 不同,结果为 false。
【讨论】:
以上是关于请求正文中的布尔参数在 NestJS api 中始终为真的主要内容,如果未能解决你的问题,请参考以下文章
REST API 最佳实践:查询字符串中的参数与请求正文中的参数
Azure 数据工厂 - 尝试将参数添加到 REST API 请求正文中的动态内容
如何在 NestJS 控制器处理程序的请求中获取“已验证的正文”和“已验证的用户”?