NestJS/Express:不区分大小写的Body Fields



我正在努力使我的请求dto的字段不区分大小写。

export class ExampleDto {
dateOfBirth?: string
}

现在我想接受

  • { "dateofbirth": "19880101" }
  • { "dateOfBirth": "19880101" }
  • { "DATEOFBIRTH": "19880101" }

我的第一个想法是实现一个中间件,它只查看传入的正文并"扩展"它。与低&所有输入字段的大写映射。

但由于驼峰大小写,这不符合我的要求,我绝对希望保持默认值

有什么好主意吗?

您可以创建一个自定义Pipe,在其中尝试不同的选项并最终返回Dto实例:

export class CaseInsensitiveExampleDtoPipe implements PipeTransform{
transform(body: any, metadata: ArgumentMetadata): ExampleDto {
const dto = new ExampleDto();
dto.dateOfBirth = body.dateOfBirth || body.dateofbirth || body.DATEOFBIRTH;
return dto;
}
在你的控制器中,你可以这样使用它:
@UsePipes(new CaseInsensitiveExampleDtoPipe())
async postNewExample(@Body() exampleDto: ExampleDto) {
// ...
}

由于JavaScript属性在初始化后就开始存在,因此您无法"看到"。dateOfBirth?: string的定义,因此您将无法将其与收到的JSON进行匹配。

一个可能的解决方案是使用构造函数强制创建所有DTO的属性:
export class ExampleDto {
dateOfBirth: string
constructor(dateOfBirth: string){
this.dateOfBirth = dateOfBirth;
}
}
然后,您将能够遍历ExampleDto的属性并将它们与管道匹配(接收到的类型可以从metadata派生):
@Injectable()
export class IgnoreCasePipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
const dto = new metadata.metatype;
const dtoKeys = Object.getOwnPropertyNames(dto);
Object.keys(value).forEach(key => {
const realKey = dtoKeys.find(dtoKey => dtoKey.toLocaleLowerCase() === key.toLocaleLowerCase());
if (realKey) {
dto[realKey] = value[key];
}
});
return dto;
}
}

在main中全局注入。请记住,您需要为每个DTO创建一个构造函数。

注意:这将适用于单级类。如果你想在你的类中支持people: PersonDto[]之类的东西,那么你需要递归地找到所有嵌套的键并匹配它们——就像这样。

最新更新