前言
当我们在dto层定义好参数字段后,客户端在调用时传入了未定义的字段,此时我们需要报错告知客户端这个字段不存在,在nest中默认不会报错,本文将分享这个问题的解决方案,欢迎各位感兴趣的开发者阅读本文。
场景概述
我们继续用文章“使用NestJS搭建服务端应用[1]”所创建的项目,以此为基础来描述这个问题,如下所述代码所示,我们在AppDto.ts
中定义了三个字段。
- id
- title
- name
export class AppDto { @MinLength(5) @IsString() public id!: string; @IsString() public title!: string; @IsString() public name!: string; }
随后,我们启动项目,使用postman
调用接口,传多一个age
字段,这个字段我们未曾在AppDto
中定义,调用接口后,如下图所示,接口调用成功了,这并不是我们的期望结果,我们希望它报错。
image-20220214230136474
❝小tips:在Java中,我们在实体类中定义了字段,SpringBoot在处理客户端参数,对其进行序列化时,就可以直接抛出异常。
解决方案
在解决这个问题时,我在网络上检索了一波,没发现合适的方案,最后,求助了一波网友,得到的方案是自己在controller层写方法遍历参数的所有key对其进行校验,然后抛出异常。我觉得这是下下策,自己写方法校验太繁琐了,不利于维护。
尝试解决
突然,有个网友告诉了我forbidUnknownValues
这个关键词,打开了我的眼界,让我看到了希望。
image-20220214231807475
经过一番检索后,找到了有关它的详细文档,如下所示:
image-20220214232409975
看到这个后,嘴角疯狂上扬,在main.ts
中的全局管道总开启了这个配置项,代码如下所示:
async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe({ forbidUnknownValues: true })); await app.listen(3000); } bootstrap();
本以为万事大吉了,执行结果却不尽人意🌚
image-20220214233144828
问题解决
此时的我,陷入了沉思,按照描述应该是这个参数才对啊。沉思间,我看到了whitelist
与forbidNonWhitelisted
字段。
- whitelist 如果设置为true,验证器将剥离任何不使用任何装饰器的属性的验证对象。
- forbidNonWhitelisted 如果设置为true,则验证程序将抛出异常,而不是剥离非白名单属性。
dto中未声明的字段一定是没有装饰器的,满足了whitelist
字段,白名单的属性验证不通过时,让验证器抛出异常,正好满足了forbidNonWhitelisted
属性,这样应该就成了吧,代码如下所示:
async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes( new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }) ); await app.listen(3000); } bootstrap();
继续使用postman进行调用接口进行测试,完美实现了我们想要的效果。
image-20220214234129804
示例代码
本文中所列举的完整代码请移步:
- main.ts[2]
- AppDto.ts[3]
写在最后
至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站[4],进一步了解。
- 公众号无法外链,如果文中有链接,可点击下方阅读原文查看😊