5

问题:如何跨文件拆分 swagger 定义?该领域的可能性是什么?问题详情描述如下:

我想要的例子 - 在 RAML

我确实有 RAML 方面的经验,我所做的是,例如:

/settings:
  description: |
    This resource defines application & components configuration
  get:
    is: [ includingCustomHeaders ]
    description: |
      Fetch entire configuration
    responses:
      200:
        body:
          example: !include samples/settings.json
          schema: !include schemas/settings.json

最后两行在这里很重要!include <filepath>- 在 RAML 中,我可以将整个合同拆分为许多文件,这些文件只是被 RAML 解析器动态包含(并且所有基于 RAML 的工具都使用 RAML 解析器)。

我从中得到的好处是:

  • 我的合同更清晰,更容易维护,因为模式不是内联的
  • 但这真的很重要:我可以在其他工具中重用模式文件来进行验证、模拟生成、存根、生成测试等。换句话说,通过这种方式,我可以在合同(RAML,本例)和其他工具(非 RAML,非 swagger,仅基于 JSONschema 的工具)中重用模式文件。

回到大摇大摆

据我所知,swagger 支持$ref允许加载外部文件的关键字。但是这些文件是通过 HTTP/AJAX 获取的,还是只是本地文件?

是整个规范都支持它,还是只是一些支持它而一些不支持它的工具?

我在这里发现的是,swagger 的输入必须是一个文件。这对于大型项目来说非常不方便:

  • 因为尺寸
  • 并且因为如果我想使用非招摇的东西,我就不能重用模式

或者,换句话说,我可以用 swagger 实现与 RAML 相同的效果吗 - 在拆分文件方面?

4

4 回答 4

6

该规范允许在多个位置进行引用,但不是在任何地方。这些引用的解析取决于规范的托管位置以及您要执行的操作。

对于渲染动态用户界面之类的事情,是的,您确实需要最终将整个定义加载到可能由许多文件组成的“单个对象”中。如果执行代码生成,则可以直接从文件系统加载定义。但最终还是有 swagger 解析器在做解析,这在 Swagger 中比其他定义格式更细粒度和可控。

在您的情况下,您将使用指向架构引用的 JSON 指针:

responses:
  200:
    description: the response
    schema:

通过本地参考

      $ref: '#/definitions/myModel'

通过绝对参考:

      $ref: 'http://path/to/your/resource'

通过相对引用,这将是“相对于加载此文档的位置”

      $ref: 'resource.json#/myModel

通过内联定义

      type: object
      properties:
        id:
          type: string
于 2016-02-22T15:58:33.773 回答
2

当我使用引用拆分 OpenAPI V3 文件时,我尽量避免使用sock Drawer 反模式,而是对 YAML 文件使用功能分组。

我还使每个 YAML 文件本身都是有效的 OpenAPI V3 规范。

我从openapi.yaml文件开始。

openapi: 3.0.3
info:
  title: MyAPI
  description: |
    This is the public API for my stuff.
  version: "3"
tags:
  # NOTE: the name is needed as the info block uses `title` rather than name
  - name: Authentication
    $ref: 'authn.yaml#/info'
paths:
  # NOTE: here are the references to the other OpenAPI files 
  #  from the path.  Note because OpenAPI requires paths to
  #  start with `/` and that is already used as a separator
  #  replace the `/` with `%2F` for the path reference.
  '/authn/start':
    $ref: 'authn.yaml#/paths/%2Fstart'

然后在功能组中:

openapi: 3.0.3
info:
  title: Authentication
  description: |
    This is the authentication module.
  version: "3"
paths:
  # NOTE: don't include the `/authn` prefix here that top level grouping is
  #  in the `openapi.yaml` file.
  '/start':
    get:
      responses:
        "200":
          description: OK

通过这种分离,您可以独立地测试每个文件或作为一个组的整个 API。

可能有些地方您会重复自己,但这样做可以限制在使用“通用”库时对其他 API 端点进行破坏性更改的机会。

但是,您仍然应该有一些通用定义库,例如:

  • 错误
  • 安全

这种方法有一个限制,那就是“鉴别器”(虽然它可能是一个 ReDoc 问题,但是如果您的类型在openapi.yamlReDoc 之外具有鉴别器,则无法正确呈现。

于 2020-04-11T17:57:45.040 回答
1

有关如何将 Swagger 文档拆分为多个文件的详细信息,请参阅此答案。这是使用 JSON 完成的,但同样的概念也适用于 RAML。

编辑:在此处添加链接内容

Swagger JSON 的基本结构应如下所示:

{
"swagger": "2.0",
"info": {
    "title": "",
    "version": "version number here"
},
"basePath": "/",
"host": "host goes here",
"schemes": [
    "http"
],
"produces": [
    "application/json"
],
"paths": {},
"definitions": {}
}

和是您需要插入 API 支持的路径和描述响应对象的模型定义的地方pathsdefinitions您可以动态填充这些对象。一种方法是为每个实体的路径和模型创建一个单独的文件。

假设您的 API 中的一个对象是“汽车”。

小路:

{
"paths": {
    "/cars": {
        "get": {
            "tags": [
                "Car"
            ],
            "summary": "Get all cars",
            "description": "Returns all of the cars.",             
            "responses": {
                "200": {
                    "description": "An array of cars",
                    "schema": {
                        "type": "array",
                        "items": {
                            "$ref": "#/definitions/car"
                        }
                    }
                },
                "404": {
                    "description": "error fetching cars",
                    "schema": {
                        "$ref": "#/definitions/error"
                    }
                }
            }
        }
    }
}

模型:

{
"car": {
    "properties": {
        "_id": {
            "type": "string",
            "description": "car unique identifier"
        },
        "make": {
            "type": "string",
            "description": "Make of the car"
        },
        "model":{
            "type": "string",
            "description": "Model of the car."
        }
    }
}
}

然后,您可以将它们中的每一个放在它们自己的文件中。当您启动服务器时,您可以获取这两个 JSON 对象,并将它们附加到基本 swagger 对象(pathsdefinitions)中的适当对象,并将该基本对象作为 Swagger JSON 对象提供。

您还可以通过仅在服务器启动时执行一次附加来进一步优化这一点(因为 API 文档在服务器运行时不会更改)。然后,当点击“serve Swagger docs”端点时,您可以只返回您在服务器启动时创建的缓存 Swagger JSON 对象。

/api-docs“serve Swagger docs”端点可以通过捕获如下请求来拦截:

app.get('/api-docs', function(req, res) {
  // return the created Swagger JSON object here
});
于 2016-02-22T16:14:42.863 回答
0

您可以使用 $ref 但没有很好的灵活性,我建议您使用诸如“Yamlinc”之类的外部工具处理 YAML,该工具使用“$include”标签将多个文件混合为一个。

阅读更多:https ://github.com/javanile/yamlinc

于 2018-02-13T23:26:52.403 回答