如何在NestJS Swagger中定义混合类型数组请求体?
在NestJS中配置Swagger多类型Feature请求体
要实现这种动态Feature结构的Swagger文档,核心是利用OpenAPI的discriminator特性配合anyOf,让Swagger能识别不同type对应的字段结构。以下是具体实现步骤:
步骤1:定义各个Feature的DTO类
为每种Feature创建独立的DTO,并通过@ApiProperty固定type字段的值:
import { ApiProperty } from '@nestjs/swagger'; import { IsString, IsUUID, IsISO8601 } from 'class-validator'; // 过期日期Feature export class ExpiredDateFeatureDto { @ApiProperty({ enum: ['expiredDate'] }) @IsString() type: 'expiredDate'; @ApiProperty({ format: 'date-time' }) @IsISO8601() expiredDate: string; } // 推荐人Feature export class ReferrerFeatureDto { @ApiProperty({ enum: ['referrer'] }) @IsString() type: 'referrer'; @ApiProperty({ format: 'uuid' }) @IsUUID() refererId: string; } // 激励购买Feature(修正拼写:pursache → purchase) export class MotivatedPurchaseFeatureDto { @ApiProperty({ enum: ['motivated-purchase'] }) @IsString() type: 'motivated-purchase'; @ApiProperty({ format: 'uuid' }) @IsUUID() purchase: string; }
步骤2:定义创建优惠券的请求体DTO
在主DTO中,为features字段配置anyOf并指定discriminator,让Swagger根据type字段区分不同结构:
import { ApiProperty } from '@nestjs/swagger'; import { IsArray, ValidateNested } from 'class-validator'; import { Type } from 'class-transformer'; import { ExpiredDateFeatureDto, ReferrerFeatureDto, MotivatedPurchaseFeatureDto } from './feature-dtos'; export class CreateCouponDto { @ApiProperty({ description: '优惠券码' }) @IsString() code: string; @ApiProperty({ description: '优惠券特性列表', isArray: true, anyOf: [ { $ref: '#/components/schemas/ExpiredDateFeatureDto' }, { $ref: '#/components/schemas/ReferrerFeatureDto' }, { $ref: '#/components/schemas/MotivatedPurchaseFeatureDto' }, ], discriminator: { propertyName: 'type', mapping: { expiredDate: '#/components/schemas/ExpiredDateFeatureDto', referrer: '#/components/schemas/ReferrerFeatureDto', 'motivated-purchase': '#/components/schemas/MotivatedPurchaseFeatureDto', }, }, }) @IsArray() @ValidateNested({ each: true }) @Type(() => Object, { keepDiscriminatorProperty: true, discriminator: { property: 'type', subTypes: [ { value: ExpiredDateFeatureDto, name: 'expiredDate' }, { value: ReferrerFeatureDto, name: 'referrer' }, { value: MotivatedPurchaseFeatureDto, name: 'motivated-purchase' }, ], }, }) features: (ExpiredDateFeatureDto | ReferrerFeatureDto | MotivatedPurchaseFeatureDto)[]; }
步骤3:在控制器中使用DTO
在POST接口上用@Body()接收该DTO,并通过@ApiBody指定请求体类型:
import { Controller, Post, Body } from '@nestjs/common'; import { ApiOperation, ApiBody } from '@nestjs/swagger'; import { CreateCouponDto } from './create-coupon.dto'; @Controller('code') export class CouponController { @Post() @ApiOperation({ summary: '创建优惠券' }) @ApiBody({ type: CreateCouponDto }) createCoupon(@Body() createCouponDto: CreateCouponDto) { // 业务逻辑 return createCouponDto; } }
纯OpenAPI规范写法
如果直接编写OpenAPI YAML规范,对应的结构如下:
openapi: 3.0.3 info: title: Coupon API version: 1.0.0 paths: /code: post: summary: 创建优惠券 requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateCouponRequest' responses: '201': description: 优惠券创建成功 components: schemas: CreateCouponRequest: type: object properties: code: type: string description: 优惠券码 features: type: array items: anyOf: - $ref: '#/components/schemas/ExpiredDateFeature' - $ref: '#/components/schemas/ReferrerFeature' - $ref: '#/components/schemas/MotivatedPurchaseFeature' discriminator: propertyName: type mapping: expiredDate: '#/components/schemas/ExpiredDateFeature' referrer: '#/components/schemas/ReferrerFeature' motivated-purchase: '#/components/schemas/MotivatedPurchaseFeature' description: 优惠券特性列表 ExpiredDateFeature: type: object required: [type, expiredDate] properties: type: type: string enum: [expiredDate] expiredDate: type: string format: date-time ReferrerFeature: type: object required: [type, refererId] properties: type: type: string enum: [referrer] refererId: type: string format: uuid MotivatedPurchaseFeature: type: object required: [type, purchase] properties: type: type: string enum: [motivated-purchase] purchase: type: string format: uuid
关键说明
discriminator是核心:指定type作为区分字段,Swagger会根据该字段的值自动匹配对应的Schema结构。anyOf定义了数组元素的可选类型,配合discriminator后,Swagger UI会提供下拉选择不同的Feature类型,并自动展示对应字段。- 类验证器的
@Type装饰器配合discriminator配置,确保NestJS能正确将请求体转换为对应的DTO实例。
内容的提问来源于stack exchange,提问作者srhuevo
相关产品推荐
相关产品推荐

