You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:27:39