如何使Swagger Codegen为您的团队工作

Swagger Codegen是开源API客户端代码生成器,对于您的团队而言,它可以成为功能极其强大,节省时间的协作工具。 与大多数功能强大的工具一样,它可能无法立即满足您的需求。 为了让Swagger Codegen真正为您和您的团队工作,了解Swagger Codegen的工作方式将很有帮助。 但是,首先您可能会问,为什么?

“我们鼓励您开发程序员的三大美德: 懒惰,不耐烦和傲慢。” — LarryWall,O’Reilly And Associates的ProgrammingPerl(第一版)

在讨论代码生成工具时,我会一开始就不提拉里·沃尔(Larry Wall)的“程序员的三种美德”。可以为懒惰辩护。

在这种情况下,懒惰由拉里·沃尔(Larry Wall)在其著名的《 编程Perl》一书的词汇表中解释为:“使您尽全力减少总体能源消耗的质量。 它使您可以编写省力的程序,其他人会发现它有用……”

现在,当拉里·沃尔(Larry Wall)赞扬程序员懒惰的优点时,他并不是指偷工减料和做懒惰的事情,例如不编写单元测试。 拉里·沃尔(Larry Wall)对懒惰的定义在任何情况下都不应视为对懒惰的辩护。 但是,如果您正确地做到了“懒惰”,并且希望您在阅读本文后会如此,那么使用Swagger Codegen不仅意味着减少自己的能源消耗,而且还意味着团队中所有成员的能源消耗减少。

您无需编写,维护或担心自动生成的代码的一致性! 您可以节省工作和精力,例如编写有关代码生成的博客。 😇

但是,等等,在我们开始凭空生成代码之前,我们必须谈论作为团队达到目标所需要的东西。

OpenAPI规范(以前称为Swagger规范)是“与RESTful API无关的语言的接口 ”,它使各种精通不同编程语言的开发人员可以以每个人都能理解的方式讨论REST API。 该规范允许开发人员创建合同,该合同定义API的工作方式以及应该在任何人编写一行代码之前执行的操作。 这样一来,将创建并维护API的开发人员及其客户就非常特定的合同达成协议,并说:“如果我将带有这些标头的正文发布到此端点,那么我期望以这种格式进行响应。”

举一个具体的例子,我邀请您查看此PetAPI应用程序的OpenAPI规范。 当您了解有关OpenAPI规范的更多信息时,Pet Store示例就是一个非常熟悉的示例。 这是每个开发人员为每种新语言实现代码生成规则时使用的参考点。 集成测试始终根据OpenAPI Initiative的Github Repo中的OpenAPI规范执行。

简要回顾一下`petstore.yaml`我们可以看到已经定义了一个简单但完整的API。 根据此规范中定义的要求,我们可以实现一个后端服务,该服务返回数据库中所有宠物的列表,或将新宠物写入数据库,然后发布到API。 在前端,我们可以构建与API交互所需的模型,并实现可用于调用端点以获取新宠物或发布新宠物的正确服务。

我们可以做所有的事情……但是作为“懒惰”程序员,我们可以使用Swagger Codegen代替它!

在使用Swagger Codegen之前,您需要在本地安装它。 有多种不同的方式来安装和使用Swagger Codegen。 为了最大程度地控制修改项目以适应我们的需求(并与该博客一起进行),获取Swagger Codegen的最佳方法是克隆整个存储库:https://github.com/ swagger-api / swagger-codegen。 在本地拥有项目后,需要运行mvn clean package 。 如果成功完成,您将在目录modules/swagger-codegen-cli/target/ swagger-codegen-cli.jar创建的swagger-codegen-cli.jar

注— 如果您的环境中没有`mvn`命令行工具,则可以在 此处 找到有关下载和安装Maven的说明

该.jar文件是一个命令行工具,可在您准备生成代码后提供使用Swagger Codegen所需的唯一界面。 让我们以一个简单的示例为例,并生成Swift客户端模型以与我们之前介绍的Pet Store API进行接口。

让我们为实验创建一个干净的工作目录:

  mkdir〜/ PetStoreApp;  cd〜/ PetStoreApp; 打开。 

将swagger-codegen-cli.jar文件复制到PetStoreApp文件夹中,然后将petstore.yaml文件下载到同一文件夹中(右键单击浏览器中的网页>另存为…)

现在,您的PetStoreApp文件夹中应该有两个文件。

在终端中,确保您位于/ PetStoreApp目录中,并运行以下命令:


java -jar swagger-codegen-cli.jar生成-i petstore.yaml -l swift4 -Dmodels

您可以在此处找到可用于生成代码的所有选项的全部细分。 您还可以将.help文件与.jar文件一起使用,以获取有关此命令的更多详细信息。 但是现在,让我们分解上面的简单命令:

· java -jar swagger-codegen-cli.jar

Java命令行工具允许我们传递Java ARchive(JAR)文件并在命令行中执行它。 这样,我们可以运行Swagger Codegen命令行工具。

· generate

生成是传递给Swagger Codegen CLI工具的命令。 这是调用该工具的主要方式,传递给CLI工具的其他所有内容都是用于修改generate命令执行的选项。

· -i petstore.yaml

这是输入规范文件。 在此示例中,我们传入了Pet Store API yaml文件。 Swagger Codegen将使用此规范文件来生成我们的代码。

· -l swift4

在这里,我们指定希望Swagger Codegen为我们的应用程序生成客户端Swift代码。 我们指定了Swift 4,但是Swagger Codegen也支持Swift 2和Swift 3。

· -Dmodels

最后一个选项指定我们只想为我们的API生成模型文件。 这包括规范底部的OpenAPI规范的“定义”部分中定义的模型。 Swagger Codegen可以在客户端上为您生成网络代码的模拟实现。 为了使该博客简单,我将讨论仅限于生成的模型,并将生成的网络代码留给另一个博客。 也许😀

从PetStoreApp目录运行上述命令后,您将看到以下内容:

请注意,这次Swagger Codegen为我们生成的唯一文件是模型文件。 这些是在`petstore.yaml ”文件的`definitions`部分中定义的模型文件,我们在用来生成这些模型的generate命令中引用了这些文件。 如上所述,我们使用的`-Dmodels`标志是向Swagger Codegen Tool发出信号的信号,即我们只希望生成模型。 单独生成模型是Swagger Codegen的一项非常强大的功能,因为它允许我们做一些事情。

  1. 它使我们可以自由使用我们应用程序中的任何网络库。 Swagger Codegen支持为RXSwift,Alamofire和PromiseKit构建所有网络请求管理代码。
  2. 生成模型可以减少在服务的后端和前端定义共享模型时可能发生的人为错误。 即使您拼写错误的属性名称,也可以保证在网络请求的两端以完全相同的方式拼写错误的属性!
  3. 如果您的应用程序使用很多不同的模型与后端服务进行通信,或者这些模型经常更改,则可以显着减少从头维护或编写这些模型所需的时间和精力。 如果您的前端和后端服务以不同的语言实现,则尤其如此。

Swagger Codegen基于我们作为输入规范传入的petstore.yaml文件为我们创建了三个新文件。 让我们仔细看看Pet.swift文件。

 公用结构宠物:可编码{ 
公共变量_id:Int64
公共变量名称:字符串
公共var标签:字符串? public init(_id:Int64,name:String,tag:String?){
self._id = _id
self.name =名称
self.tag =标签
}公共枚举CodingKeys:字符串,CodingKey {
case _id =“ id”
案例名称
案例标签
}
}

将生成的Swift模型与OpenAPI规范中的原始定义进行比较时,我们会清楚地看到这种关系。 该对象的原始OpenAPI规范如下所示:

 宠物: 
需要:
- ID
- 名称
特性:
ID:
类型:整数
格式:int64
名称:
类型:字符串
标签:
类型:字符串

即使数据格式略有不同,OpenAPI规范中也提供了构建Swift对象(或任何其他语言的对象)所需的所有信息。 但是,OpenAPI规范不是最终从中生成Swift对象的数据。 在使用特定语言创建对象之前,Swagger Codegen会基于OpenAPI规范生成一个中间状态。

虽然仍在/ PetStoreApp目录中,但是我们可以运行与我们刚运行的命令类似的命令,但是这次我们将传递命令以向我们显示该中间状态。

  java -jar swagger-codegen-cli.jar生成-i petstore.yaml -l swift4 -DdebugModels 

传递-DdebugModels标志会将大量数据转储到终端。 为了居中,您可以在终端”importPath” : “/Models.Pet”搜索该字符串”importPath” : “/Models.Pet”

这是根据上述OpenAPI规范生成的代表Pet模型的中间数据对象。 您会注意到,它具有与OpenAPI规范相同的信息,但是格式略有不同。 这些数据已经过格式化,可以轻松地用于生成Swift类。 例如,您将看到此数据对象的属性之一是变量数组。 这些变量中的每一个都是我们Pet类的一个属性,该对象为我们提供了有关这些变量的许多非常具体的信息。 这是我们仅可以看到的有关id属性的数据:


“ vars”:[{
“ baseName”:“ id”,
“ getter”:“ getId”,
“ setter”:“ setId”,
“数据类型”:“ Int64”,
“ datatypeWithEnum”:“ Int64”,
“ dataFormat”:“ int64”,
“名称”:“ _ id”,
“ defaultValueWithParam”:“ = data.id;”,
“ baseType”:“ Int64”,
“ jsonSchema”:“ {\ n \” type \“:\”整数\“,\ n \” format \“:\” int64 \“ \ n}”,
“ exclusiveMinimum”:否,
“ exclusiveMaximum”:否,
“ hasMore”:是的,
“必填”:是的,
“ secondaryParam”:否,
“ hasMoreNonReadOnly”:是的,
“ isPrimitiveType”:true,
“ isContainer”:否,
“ isNotContainer”:是的,
“ isString”:false,
“ isNumeric”:是的,
“ isInteger”:false,
“ isLong”:是的,
“ isNumber”:false,
“ isFloat”:false,
“ isDouble”:false,
“ isByteArray”:false,
“ isBinary”:否,
“ isFile”:false,
“ isBoolean”:false,
“ isDate”:false,
“ isDateTime”:false,
“ isUuid”:false,
“ isListContainer”:false,
“ isMapContainer”:false,
“ isEnum”:false,
“ isReadOnly”:false,
“ vendorExtensions”:{
“ x-swift-optional-scalar”:是的,
“ x代码生成转义的属性名称”:true
},
“ hasValidation”:false,
“ isInherited”:false,
“ nameInCamelCase”:“ Id”
“ isXmlAttribute”:false,
“ isXmlWrapped”:false
}

一些非常有用的Swift开发人员为我们创建了一些神奇的东西。 一个特定的示例是“ name”属性。 您会注意到, “name”“_id” ,但“baseName”“id” 。 这是有用的,因为id是Obj-C中的保留关键字。

为了使此生成的代码与Obj-C更具互操作性,您会注意到,如果向上滚动,即使我们的Pet模型被定义为具有属性名“id” ,该情况也已在生成的Swift类中安全处理。 。 这样,当我们在客户端使用该对象时,我们会将属性引用为“_id” 。 但是,无论何时将对象序列化为JSON以发送到服务器,都将使用正确的“ id”属性名称。

但是这里似乎仍然缺少一些东西……我们如何从一个OpenAPI规范,到这个笨拙的JSON blob,再到一个完美呈现的Swift类? 答案是留胡子的模板!

小胡子模板系统用于将变量值插入静态文本模板。 在“胡子文档”中最简单的示例中,很清楚,胡子模板系统是如何获得其名称的。 无数的侧面看起来像胡须的花括号用于标识应替换的变量值。

 模板:{{#person?}} 
{{name}},您好!
{{/ person?}}哈希:{
“人?”:{“名称”:“乔恩”}
}输出:嗨,乔恩!

使用相同的系统,我们不仅可以为用Swift编写的移动应用程序生成模型 ,而且可以为我们可能需要的每种语言生成代码 。 继续使用Swift示例,让我们研究一下如何使用髭模板系统为Swift对象创建模板。

可以在此处找到Swift 4模型对象的Swagger Codegen实现。 但是,让我们制作一个简单的版本来说明一些基本知识:

 模板:import Foundationpublic类{{classname}}:可编码{ 
{{#vars}}
公共变量{{name}}:{{{datatype}}} {{^ required}}?{{/ required}} {{#defaultValue}} = {{{defaultValue}}} {{/ defaultValue}}
{{/ vars}} init({{#vars}} {{name}}:{{{datatype}}} {{^ required}}?{{/ required}} {{^ isFinal}},{{/ isFinal}} {{/ vars}}){
{{#vars}}
自我。{{name}} = {{name}}
{{/ vars}}
}
}哈希:{
“ classname”:“ Pet”,
“ vars”:[
{
“名称”:“ _ id”,
“数据类型”:“ Int64”,
“必填”:是的,
“ defaultValue”:1
},
{
“名称”:“名称”,
“数据类型”:“字符串”,
“必填”:false,
“ isFinal”:正确
}
]
}输出:import Foundationpublic class Pet:可编码{
public var _id:Int64 = 1 public var名称:String?init(id:Int64,name:String?){
self._id = _id
self.name =名称
}
}

我建议采用上述模板和JSON哈希,然后将其插入简单的Mustache演示应用程序中。 在这里,您可以修改哈希值或更改胡子模板,以查看是否可以改进或创建新功能。 您如何重新创建在本博客开始时在Swift对象中看到的编码键枚举? 您如何修改胡须模板,以使使用此模板创建的所有数据模型都符合等价或可哈希协议? 如果您能够回答这些问题,那么您就可以成为那种“懒惰”的程序员,他们可能再也不需要编写或更新另一个数据模型了!

Swagger Codegen的大多数用户无需修改Swagger Codegen库本身基础的胡须模板,因为每种语言的胡须模板的默认实现已涵盖了大多数用例。 但是,还有其他方法可以修改Swagger Codegen的输出,而无需修改胡子模板。 修改不同语言模板的行为的默认方法是传入配置对象。

您可以使用此命令找出每种语言支持的配置属性:

  java -jar swagger-codegen-cli.jar配置帮助-l  

(可选)使用库来管理响应。 目前PromiseKit,RxSwift可用。

  responseAs 
(可选)使用库来管理响应。 目前PromiseKit,RxSwift可用。 拆包必填
将响应中的“必需”属性视为非可选(如果API返回null而不是json模式中指定的必需选项,则会使应用程序崩溃
```

要使用这些属性,您需要创建一个新文件,您可以在其中创建JSON对象以作为新参数传递给Swagger Codegen CLI工具。 虽然仍在您先前创建的PetStoreApp文件夹中,但是您可以运行以下命令来创建一个JSON对象,该对象将RxSwift指定为用于处理HTTP响应的库:

 回声{“ responseAs”:“ RxSwift”}> config.json 

现在,您可以将此config.json文件传递到原始的CLI命令中以生成我们的代码,同时删除指令-Dmodels并允许Swagger Codegen生成除数据模型之外的所有文件:

  java -jar swagger-codegen-cli.jar生成-i petstore.yaml -l swift4 -c config.json 

现在,您不仅应该对Swagger Codegen工具可以做什么,而且应该如何使用它们来体现“懒惰”的美德,也应该有一个很好的了解。 但是,我们仍只是勉强了解Swagger Codegen这个功能强大的工具的概况,以及该工具如何帮助您减少总体能源消耗,如Larry Wall。

Swagger Codegen的开发非常活跃,并且社区参与度很高,因此一定要查看其Github页面,了解Swagger Codegen的最新信息。 此外,除了Swagger Codegen之外,还有其他一些出色的Codegen工具。 我很想听听您喜欢的其他工具或您的使用经验。 如有任何疑问或意见,请随时在Twitter上与我联系。


公开声明:这些观点是作者的观点。 除非在本帖子中另有说明,否则Capital One不与任何提及的公司有关联或认可。 使用或显示的所有商标和其他知识产权均为其各自所有者的所有权。 本文为©2018 Capital One。