NestJs/swagger: 在不使用DTO类的情况下定义参考模式

9

我有一个应用程序,其中我按照Open-API规范将API响应模式定义为纯JavaScript对象。目前,我将其传递给@nestjs/swagger中的ApiResponse装饰器,如下所示:

class CatsController {

  @Get()
  @ApiResponse({
    status: 200,
    schema: catSchema // plain js object imported from another file
  })
  getAll() {}
}

这很好用。然而,输出的 Open-API 规范包含了每个使用 catSchema 的终端点的冗长模式。相反,我希望输出的 Swagger 文件将 catSchema 放在 components 部分下,并在路径部分有对应的 $ref

components:
  schemas:
    Cat:
      properties:
        name:
          type: string
paths:
  /cats/{id}:
    get:
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Cat'

目前看来,唯一的方法就是将模式定义为DTO类,并针对每个类属性使用ApiProperty装饰器。在我的情况下,这意味着我必须重构所有纯对象模式以成为DTO类。

有没有一种方法可以将原始模式输入到库中并获得预期的结果呢?

// instead of this:
class CatDto {
  @ApiProperty()
  name: string;
}

// I want to do:
const catSchema = {
  type: 'object',
  properties: {
    name: { type: 'string' }
  }
}

简而言之,不行。 这背后的原因是:@ApiProperty是Swagger在NestJs中理解模式的标签,并不支持内联模式设计。你能详细解释一下你想如何传递模式吗? - Tanmoy Bhattacharjee
感谢@TanmoyBhattacharjee的回复。 我想直接将内联模式传递给@ApiResponse。它运行良好,除了不支持$ref模式。输出在响应部分下直接包含模式。这有意义吗? - Pubudu Dodangoda
3个回答

5
经过数天的试错,我使用JavaScript中的一个有趣技巧成功实现了此操作。
首先,我将OpenAPI规范创建为普通对象(如问题中所要求)。然后将其传递给一个新的装饰器,在其中进行魔法操作。
在装饰器中,我创建了一个DTO类,并使用预定义的名称将属性从普通对象映射到DTO类。关键部分是动态地为其命名。可以通过以下技巧实现这一点。
const dynamicName = 'foo'; // passed as a parameter to the decorator

class IntermediateDTO {
  @ApiProperty(schema) // schema as a plain object
  data: any;
}

const proxyObject = {
  [dynamicName] = class extends IntermediateDTO {}
}

通过使用代理对象,并将class extends IntermediateDTO {}分配给其中的属性,实现动态命名条目。现在,具有动态名称的新DTO可以传递给@nestjs/swaggerApiResponse装饰器,以达到预期结果。

这还能用吗?您能否澄清@ApiResponse()的用法? - Daniel

5

我猜这也可以通过使用 getSchemaPathApiExtraModels 来实现:

import { ApiExtraModels, ApiResponse, getSchemaPath } from '@nestjs/swagger';

@ApiExtraModels(CatDto) // for CatDto to be found by getSchemaPath()
@ApiResponse({
  schema: {
    '$ref': getSchemaPath(CatDto)
  }
})

更多关于额外模型的信息请参考:https://docs.nestjs.com/openapi/types-and-parameters#extra-models

在我的情况下,这意味着我需要将open-api规范中的所有普通对象模式重构为DTO类。

您不需要手动注释对象,您也可以使用此插件(可选):https://docs.nestjs.com/openapi/cli-plugin


谢谢你的回答。我的问题更多地是关于坚持使用普通模式的JSON,而不是将它们转换为DTO类。 - Pubudu Dodangoda

1

我不知道这是否是你想要的,我是这样做的

@ApiResponse({
    status: 200,
    schema: {
      example: // write the response you want here
      [    
        {
          userId: 1,
          name: 'name',
          
        },
      ],
    },
  })

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接