从Swagger (OpenAPI 2.0)规范生成服务器和客户端代码
项目描述
Swagger-to
Swagger-to可以从Swagger (OpenAPI 2.0)规范生成服务器和客户端代码;使用Python 3编写。
我们希望有一个易于编写、维护和扩展的代码生成器,并且生成的代码可读性高。
为了实现这一点,我们使用Python编写了这个工具,我们发现Python在代码生成方面远优于其他语言,如Go和Java。由于原始Swagger规范可能相当复杂,我们在解析规范并在生成代码之前引入了一个中间表示层。这一层允许我们通过操作抽象结构(如Map)而不是直接引用“原始”Swagger结构(如对象的附加属性)来显著简化代码生成,从而减少了阻抗不匹配。
底层语言(Python)、可读的生成代码和中间表示层是与其他类似代码生成项目的三个主要区别。
支持的语言
语言 |
客户端 |
服务器 |
---|---|---|
Elm |
x |
|
Go |
x |
|
Python |
x |
|
Typescript + Angular |
x |
缺失的功能
由于时间不足,我们无法涵盖所有Swagger规范。当前的生成器可以很好地处理我们所有简单和不那么简单的用例。我们相信它们也可以满足大多数其他人的需求。
以下是一个不全面的列表
匿名对象。我们在定义中不支持匿名对象。请将所有对象定义为顶级定义。
参数。Go服务器和Python客户端支持查询、主体、路径和头部参数。Elm和Typescript + Angular客户端仅支持查询、主体和路径参数。不支持Cookie参数。
默认值。由于JSON与目标语言之间的阻抗不匹配,我们不支持默认值。
响应验证。由于复杂性和运行时开销,服务器响应不会被验证。
类型层次结构。我们简单地将所有来自allOf的属性堆叠在一起,而不引入任何类型层次结构。首先,这是由于Go和Elm不支持类型层次结构。例如,您可以在Go中使用结构化类型,但那时所有数据都必须是具有接口的指针,这很笨拙。其次,这是由于便捷性,因为在中间表示层中堆叠属性意味着我们不必在上面的特定语言层中关注它们。
安装
创建虚拟环境
python3 -m venv venv3
激活它
source venv3/bin/activate
使用pip安装swagger_to
pip3 install swagger_to
用法
要生成代码,您需要调用一个swagger_to_*.py脚本之一。如果生成的代码已存在,您需要指定--force命令行参数以覆盖现有文件。
我们使用标签 name 来指定生成的代码(例如,Go服务器中的包名或Python客户端代码中的服务名)。请参见测试用例中的此示例。
Elm客户端
要从/some/path/swagger.yaml处的Swagger规范生成Elm客户端,请调用
swagger_to_elm_client.py \
--swagger_path /some/path/swagger.yaml \
--outdir /some/elm/path/src/your-client-directory
生成的代码在/some/elm/path/src/your-client-directory中的结构如下
文件 |
描述 |
---|---|
Client.elm |
Elm客户端,包含模型、编码器、解码器和HTTP请求。 |
elm-package.sample.json |
Elm JSON包,包含在Client.elm中使用的库。 |
Client中使用了两个非标准库
"NoRedInk/elm-decode-pipeline"用于以比elm-lang库支持的更可扩展的方式解码JSON对象;并且
"elm-community/json-extra"是编码Dict变量所必需的。
我们使用Elm的内置Int类型来表示32位和64位整数。请注意:Elm依赖于JavaScript,它仅使用双精度浮点数(对于整数和浮点数),这可能导致意外的截断。
Go服务器
要从/some/path/swagger.yaml处的Swagger规范生成Go服务器,请调用
swagger_to_go_server.py \
--swagger_path /some/path/swagger.yaml \
--outdir /some/go/path/src/your-server-package
生成的代码在/some/go/path/src/your-server-package中的结构如下
文件 |
描述 |
---|---|
types.go |
Go类型定义 |
jsonschemas.go |
用于验证输入的JSON模式(使用https://github.com/xeipuuv/gojsonschema) |
routes.go |
路由规范 |
handler.go |
处理器接口 |
handler_impl.sample.go |
处理器的空实现 |
Swagger中定义的所有类型都翻译到types.go。端点的路由和验证代码生成在jsonschemas.go和routes.go中。
处理器接口在handler.go中给出。您需要自行实现处理器逻辑。您可以将handler_impl.sample.go用作起点。我们通常将其复制/粘贴到handler_impl.go中,并在我们的存储库中忽略handler_impl.sample.go(例如,通过将其添加到.gitignore)。
面对Swagger(即API)的变化,我们的工作流程包括重新生成代码并使用如meld之类的diff工具同步“旧”的handler_impl.go与新的handler_impl.sample.go。
特点
参数。我们决定仅从查询、正文和路径中提取参数来生成代码。
自动生成用于提取表单数据参数的代码似乎很困难,因为它需要覆盖所有边缘情况(例如文件和重复条目)。我们仍然生成处理器函数,但将其留给程序员手动从请求中提取这些参数。
由于时间不足,我们没有实现头和cookie参数。对这些功能的贡献将非常受欢迎!
响应。自动生成的代码不会检查响应是否符合规范。我们发现这样的检查是不必要的约束,并且几乎不可能为所有用例实现。
Python客户端
要从/some/path/swagger.yaml处的Swagger规范生成Python 3客户端,请调用
swagger_to_py_client.py \
--swagger_path /some/path/swagger.yaml \
--outpath /some/py/path/your_client_module.py
生成的客户端使用requests库。
由于服务器无论如何都需要执行输入检查,我们决定不使代码生成器保持简单和可维护,仅包括对输入的基本类型检查。因此,我们故意省略了所有复杂的检查,例如字符串模式或Python整数到int32的转换。类似地,我们也不验证来自服务器的输出。
如果有时间,我们希望包括更细粒度的输入和输出验证。目前,我们在开发过程中没有遇到任何问题。
Typescript+Angular 客户端
要从 /some/path/swagger.yaml 生成 Python 客户端,请调用
swagger_to_ts_angular5_client.py \
--swagger_path /some/path/swagger.yaml \
--outpath /some/typescript/path/your_client.ts
生成的客户端使用 Angular http 库。由于与 Python 客户端相同的原因,输入和输出都不进行检查。
我们使用 TypeScript 内置的数字类型来表示 32 位和 64 位整数。请注意:TypeScript 依赖于 JavaScript,它仅使用双精度浮点数来表示整数和浮点数,这可能导致意外的截断。
样式检查
我们认为在组织中的所有 Swagger 规范中保持统一的文档风格非常重要。为此,swagger_to 包含一个工具,可以自动检查样式,例如定义名称、属性名称、描述和动词语气(使用现在时态而不是祈使语气)。要检查 /some/path/swagger.yaml 中的 Swagger 规范是否符合 Swagger 风格指南,请调用
swagger_style.py \
--swagger_path /some/path/swagger.yaml
以下检查将被执行
Swagger 名称采用驼峰式,其描述首字母大写,基本路径以斜杠开头。
顶级类型定义采用首字母大写的驼峰式,属性采用蛇形命名。
端点路径、operation_id 和参数名称采用驼峰式。
- 所有描述
以现在时态动词开头,第一个字母小写;
没有前导或尾随空格、制表符或换行符;
包含一行,或三行或更多,在这种情况下,第二行是空的;
以句号结尾。
端点路径以斜杠开头,响应包含“200”和“default”。
如果没有发现违规行为,脚本调用返回 0,在检查失败或非法使用的情况下返回 1。
示例
以下示例对开发可能很有用
Swagger API: https://github.com/Parquery/swagger-to/blob/master/tests/cases/go_server/general/swagger.yaml
Go 服务器生成的代码: https://github.com/Parquery/swagger-to/tree/master/tests/cases/go_server/general
Py 客户端生成的代码: https://github.com/Parquery/swagger-to/blob/master/tests/cases/py_client/general/client.py
Elm 客户端生成的代码: https://github.com/Parquery/swagger-to/blob/master/tests/cases/elm_client/general/Client.elm
开发
查看仓库。
在仓库根目录下创建虚拟环境
python3 -m venv venv3
激活虚拟环境
source venv3/bin/activate
安装开发依赖项
pip3 install -e .[dev]
运行 precommit.py 以在本地执行预提交检查。
版本控制
我们遵循 语义版本控制。版本 X.Y.Z 表示
X 是主版本(不兼容的),
Y 是次要版本(兼容的),
Z 是修补版本(兼容的漏洞修复)。