Nest.js如何强制将同名Query参数始终解析为字符串数组
解决方案
以下三种方案均可实现自动转换,可根据项目场景选择:
方案1:DTO + 类转换器装饰器(推荐,复用性最高)
利用你已经开启的全局ValidationPipe转换能力,配合class-transformer的@Transform装饰器定义通用字段规则,所有需要该参数的接口直接复用DTO即可:
- 定义查询参数DTO
import { Transform } from 'class-transformer'; import { IsOptional, IsString } from 'class-validator'; export class PropertyQueryDto { // 如果该参数为必填,删除@IsOptional装饰器即可 @IsOptional() @IsString({ each: true }) @Transform(({ value }) => Array.isArray(value) ? value : [value]) propertyName: string[]; }
- 控制器中绑定DTO
import { PropertyQueryDto } from './dto/property-query.dto'; @Get(':accountId') test( @Param('accountId') accountId: string, @Query() query: PropertyQueryDto, ) { // query.propertyName永远为数组类型 console.log(query.propertyName); }
方案2:自定义查询参数装饰器
如果不想使用DTO,可封装通用的数组查询参数装饰器,直接在控制器参数中使用:
- 定义自定义装饰器
import { createParamDecorator, ExecutionContext } from '@nestjs/common'; /** * 自动将查询参数转换为数组类型 * @param data 查询参数名 */ export const QueryArray = createParamDecorator( (data: string, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); const value = request.query[data]; return value ? (Array.isArray(value) ? value : [value]) : []; }, );
- 控制器中使用
import { QueryArray } from './decorators/query-array.decorator'; @Get(':accountId') test( @Param('accountId') accountId: string, @QueryArray('propertyName') propertyNames: string[], ) { console.log(propertyNames); // 永远为数组类型 }
方案3:全局配置查询解析器(适合全局生效场景)
如果项目所有同类型查询参数都需要自动转数组,可在创建Nest应用时配置Express的查询解析器,全局生效:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as qs from 'qs'; async function bootstrap() { const app = await NestFactory.create(AppModule, { // 配置查询参数解析规则,重复键自动合并为数组 queryParser: (str) => qs.parse(str, { arrayFormat: 'repeat' }), }); app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true })); await app.listen(8000); } bootstrap();
注意:该方案会全局修改查询参数解析逻辑,需要确认不会影响已有接口的参数处理。
内容的提问来源于stack exchange,提问作者shoaib30
相关产品推荐
相关产品推荐

