【问题标题】:How can one split API documentation in multiple files using Swagger 2.0如何使用 Swagger 2.0 在多个文件中拆分 API 文档
【发布时间】:2015-03-27 04:57:08
【问题描述】:

根据 Swagger 2.0 规范,有可能做到这一点。我正在使用指向另一个文件的 $ref 引用 PathObject。我们过去可以使用 Swagger 1.2 很好地做到这一点。但是 Swagger-UI 似乎无法读取另一个文件中引用的 PathObject。

这部分规范是否太新且尚不支持?有没有办法将每个“路径”的文档拆分成另一个文件?

{
    "swagger": "2.0",
    "basePath": "/rest/json",
    "schemes": [
        "http",
        "https"
    ],
    "info": {
        "title": "REST APIs",
        "description": "desc",
        "version": "1.0"
    },
    "paths": {
        "/time": {
            "$ref": "anotherfile.json"
        }
    }
}

【问题讨论】:

    标签: swagger


    【解决方案1】:

    要支持多个文件,您的库必须支持取消引用 $ref 字段。但我不建议提供带有未解析引用的 swagger 文件。我们的招摇定义有大约 30-40 个文件。通过 HTTP/1.1 传递它们可能会减慢任何阅读应用程序的速度。

    因为我们也在构建 javascript 库,所以我们已经有了一个使用 gulp 的基于 nodejs 的构建系统。对于节点包管理器 (npm),您可以找到一些支持取消引用以构建一个大的 swagger 文件的库。

    我们的基础文件如下所示(缩短):

    swagger: '2.0'
    info:
      version: 2.0.0
      title: App
      description: Example
    basePath: /api/2
    paths:
      $ref: "routes.json"
    definitions:
      example:
        $ref: "schema/example.json"
    

    routes.json 是从我们的路由文件生成的。为此,我们使用一个 gulp 目标来实现 swagger-jsdoc,如下所示:

    var gulp = require('gulp');
    var fs   = require('fs');
    var gutil = require('gulp-util');
    var swaggerJSDoc = require('swagger-jsdoc');
    
    gulp.task('routes-swagger', [], function (done) {
        var options = {
            swaggerDefinition: {
                info: {
                    title: 'Routes only, do not use, only for reference',
                    version: '1.0.0',
                },
            },
            apis: ['./routing.php'], // Path to the API docs
        };
        var swaggerSpec = swaggerJSDoc(options);
        fs.writeFile('public/doc/routes.json', JSON.stringify(swaggerSpec.paths, null, "\t"), function (error) {
            if (error) {
                gutil.log(gutil.colors.red(error));
            } else {
                gutil.log(gutil.colors.green("Succesfully generated routes include."));
                done();
            }
        });
    });
    

    为了生成 swagger 文件,我们使用构建任务来实现 SwaggerParser,如下所示:

    var gulp = require('gulp');
    var bootprint = require('bootprint');
    var bootprintSwagger = require('bootprint-swagger');
    var SwaggerParser = require('swagger-parser');
    var gutil = require('gulp-util');
    var fs   = require('fs');
    
    gulp.task('swagger', ['routes-swagger'], function () {
        SwaggerParser.bundle('public/doc/swagger.yaml', {
            "cache": {
                "fs": false
            }
        })
        .then(function(api) {
            fs.writeFile('public/doc/swagger.json', JSON.stringify(api, null, "\t"), function (error) {
                if (error) {
                    gutil.log(gutil.colors.red(error));
                } else {
                    gutil.log("Bundled API %s, Version: %s", gutil.colors.magenta(api.info.title), api.info.version);
                }
            });
        })
        .catch(function(err) {
            gutil.log(gutil.colors.red.bold(err));
        });
    });
    

    通过这个实现,我们可以维护一个相当大的 swagger 规范,并且我们不限于特殊的编程语言或框架实现,因为我们在 cmets 中定义了真正路由定义的路径。 (注意:gulp 任务也被拆分为多个文件。)

    【讨论】:

      【解决方案2】:

      虽然理论上将来可以做到这一点,但该解决方案仍未完全融入支持工具,因此目前我强烈建议将其保存在一个文件中。

      如果您正在寻找一种管理和导航 Swagger 定义的方法,我建议您使用规范的 YAML 格式,您可以在其中添加 cmets,这样可以简化导航和大型定义的拆分。

      【讨论】:

      • 如果现在可以,您能否更新一下?如果是,您能否指出正确的文档/参考实现?
      【解决方案3】:

      您还可以使用 JSON Refs 库来解析此类多文件 Swagger 规范。

      我已经在this blog post写过它

      还有this GitHub repo 来演示所有这些是如何工作的。

      【讨论】:

        【解决方案4】:

        我对这个问题的解决方案是使用下面这个包来解决参考问题

        https://www.npmjs.com/package/json-schema-ref-parser

        这是使用该库生成 swagger UI 时的代码 sn-p。我使用 Express.js 作为我的节点服务器。

        import express from 'express';
        import * as path from 'path';
        import refParser from '@apidevtools/json-schema-ref-parser';
        import swaggerUi from 'swagger-ui-express';
        
        const port = 3100;
        const app = express();
        
        app.get('/', async (req, res) => {
          res.redirect('/api-docs')
        });
        
        app.use(
          '/api-docs',
          async function (req: express.Request, res: express.Response, next: express.NextFunction) {
            const schemaFilePath = path.join(__dirname, 'schema', 'openapi.yml');
        
            try {
              // Resolve $ref in schema
              const swaggerDocument = await refParser.dereference(schemaFilePath);
              (req as any).swaggerDoc = swaggerDocument;
        
              next();
            } catch (err) {
              console.error(err);
              next(err);
            }
          },
          swaggerUi.serve,
          swaggerUi.setup()
        );
        
        app.listen(port, () => console.log(`Local web server listening on port ${port}!`));
        
        

        看看我的Github repository 看看它是如何工作的

        【讨论】:

          猜你喜欢
          • 2018-12-07
          • 2018-06-18
          • 2017-04-09
          • 2016-06-03
          • 2015-01-11
          • 1970-01-01
          • 1970-01-01
          • 2014-02-22
          • 1970-01-01
          相关资源
          最近更新 更多