swag
目录
快速开始
- 将注释添加到API源代码中,请参阅声明性注释格式。
- 使用如下命令下载swag:
1
2
3
4
|
$ go get -u github.com/swaggo/swag/cmd/swag
# 1.16 及以上版本
$ go install github.com/swaggo/swag/cmd/swag@latest
|
从源码开始构建的话,需要有Go环境(1.15及以上版本)。
或者从github的release页面下载预编译好的二进制文件。
- 在包含
main.go
文件的项目根目录运行swag init
。这将会解析注释并生成需要的文件(docs
文件夹和docs/docs.go
)。
确保导入了生成的docs/docs.go
文件,这样特定的配置文件才会被初始化。如果通用API指数没有写在main.go
中,可以使用-g
标识符来告知swag。
1
|
swag init -g http/api.go
|
- (可选) 使用
fmt
格式化 SWAG 注释。(请先升级到最新版本)
swag cli
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
swag init -h
NAME:
swag init - Create docs.go
USAGE:
swag init [command options] [arguments...]
OPTIONS:
--generalInfo value, -g value API通用信息所在的go源文件路径,如果是相对路径则基于API解析目录 (默认: "main.go")
--dir value, -d value API解析目录 (默认: "./")
--exclude value 解析扫描时排除的目录,多个目录可用逗号分隔(默认:空)
--propertyStrategy value, -p value 结构体字段命名规则,三种:snakecase,camelcase,pascalcase (默认: "camelcase")
--output value, -o value 文件(swagger.json, swagger.yaml and doc.go)输出目录 (默认: "./docs")
--parseVendor 是否解析vendor目录里的go源文件,默认不
--parseDependency 是否解析依赖目录中的go源文件,默认不
--markdownFiles value, --md value 指定API的描述信息所使用的markdown文件所在的目录
--generatedTime 是否输出时间到输出文件docs.go的顶部,默认是
--codeExampleFiles value, --cef value 解析包含用于 x-codeSamples 扩展的代码示例文件的文件夹,默认禁用
--parseInternal 解析 internal 包中的go文件,默认禁用
--parseDepth value 依赖解析深度 (默认: 100)
--instanceName value 设置文档实例名 (默认: "swagger")
|
1
2
3
4
5
6
7
8
9
10
11
12
|
swag fmt -h
NAME:
swag fmt - format swag comments
USAGE:
swag fmt [command options] [arguments...]
OPTIONS:
--dir value, -d value API解析目录 (默认: "./")
--exclude value 解析扫描时排除的目录,多个目录可用逗号分隔(默认:空)
--generalInfo value, -g value API通用信息所在的go源文件路径,如果是相对路径则基于API解析目录 (默认: "main.go")
--help, -h show help (default: false)
|
支持的Web框架
如何与Gin集成
点击此处查看示例源代码。
- 使用
swag init
生成Swagger2.0文档后,导入如下代码包:
1
2
|
import "github.com/swaggo/gin-swagger" // gin-swagger middleware
import "github.com/swaggo/files" // swagger embed files
|
- 在
main.go
源代码中添加通用的API注释:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
// @title Swagger Example API
// @version 1.0
// @description This is a sample server celler server.
// @termsOfService http://swagger.io/terms/
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host localhost:8080
// @BasePath /api/v1
// @securityDefinitions.basic BasicAuth
func main() {
r := gin.Default()
c := controller.NewController()
v1 := r.Group("/api/v1")
{
accounts := v1.Group("/accounts")
{
accounts.GET(":id", c.ShowAccount)
accounts.GET("", c.ListAccounts)
accounts.POST("", c.AddAccount)
accounts.DELETE(":id", c.DeleteAccount)
accounts.PATCH(":id", c.UpdateAccount)
accounts.POST(":id/images", c.UploadAccountImage)
}
//...
}
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run(":8080")
}
//...
|
此外,可以动态设置一些通用的API信息。生成的代码包docs
导出SwaggerInfo
变量,使用该变量可以通过编码的方式设置标题、描述、版本、主机和基础路径。使用Gin的示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package main
import (
"github.com/gin-gonic/gin"
"github.com/swaggo/files"
"github.com/swaggo/gin-swagger"
"./docs" // docs is generated by Swag CLI, you have to import it.
)
// @contact.name API Support
// @contact.url http://www.swagger.io/support
// @contact.email support@swagger.io
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
func main() {
// programatically set swagger info
docs.SwaggerInfo.Title = "Swagger Example API"
docs.SwaggerInfo.Description = "This is a sample server Petstore server."
docs.SwaggerInfo.Version = "1.0"
docs.SwaggerInfo.Host = "petstore.swagger.io"
docs.SwaggerInfo.BasePath = "/v2"
docs.SwaggerInfo.Schemes = []string{"http", "https"}
r := gin.New()
// use ginSwagger middleware to serve the API docs
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
r.Run()
}
|
- 在
controller
代码中添加API操作注释:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
package controller
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/swaggo/swag/example/celler/httputil"
"github.com/swaggo/swag/example/celler/model"
)
// ShowAccount godoc
// @Summary Show an account
// @Description get string by ID
// @Tags accounts
// @Accept json
// @Produce json
// @Param id path int true "Account ID"
// @Success 200 {object} model.Account
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPError
// @Router /accounts/{id} [get]
func (c *Controller) ShowAccount(ctx *gin.Context) {
id := ctx.Param("id")
aid, err := strconv.Atoi(id)
if err != nil {
httputil.NewError(ctx, http.StatusBadRequest, err)
return
}
account, err := model.AccountOne(aid)
if err != nil {
httputil.NewError(ctx, http.StatusNotFound, err)
return
}
ctx.JSON(http.StatusOK, account)
}
// ListAccounts godoc
// @Summary List accounts
// @Description get accounts
// @Tags accounts
// @Accept json
// @Produce json
// @Param q query string false "name search by q" Format(email)
// @Success 200 {array} model.Account
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPError
// @Router /accounts [get]
func (c *Controller) ListAccounts(ctx *gin.Context) {
q := ctx.Request.URL.Query().Get("q")
accounts, err := model.AccountsAll(q)
if err != nil {
httputil.NewError(ctx, http.StatusNotFound, err)
return
}
ctx.JSON(http.StatusOK, accounts)
}
//...
|
- 运行程序,然后在浏览器中访问 http://localhost:8080/swagger/index.html 。将看到Swagger 2.0 Api文档,如下所示:
格式化说明
可以针对Swag的注释自动格式化,就像go fmt
。
此处查看格式化结果 here.
示例:
排除目录(不扫描)示例:
1
|
swag fmt -d ./ --exclude ./internal
|
开发现状
Swagger 2.0 文档
声明式注释格式
通用API信息
示例 celler/main.go
注释 |
说明 |
示例 |
title |
必填 应用程序的名称。 |
// @title Swagger Example API |
version |
必填 提供应用程序API的版本。 |
// @version 1.0 |
description |
应用程序的简短描述。 |
// @description This is a sample server celler server. |
tag.name |
标签的名称。 |
// @tag.name This is the name of the tag |
tag.description |
标签的描述。 |
// @tag.description Cool Description |
tag.docs.url |
标签的外部文档的URL。 |
// @tag.docs.url https://example.com |
tag.docs.description |
标签的外部文档说明。 |
// @tag.docs.description Best example documentation |
termsOfService |
API的服务条款。 |
// @termsOfService http://swagger.io/terms/ |
contact.name |
公开的API的联系信息。 |
// @contact.name API Support |
contact.url |
联系信息的URL。 必须采用网址格式。 |
// @contact.url http://www.swagger.io/support |
contact.email |
联系人/组织的电子邮件地址。 必须采用电子邮件地址的格式。 |
// @contact.email support@swagger.io |
license.name |
必填 用于API的许可证名称。 |
// @license.name Apache 2.0 |
license.url |
用于API的许可证的URL。 必须采用网址格式。 |
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html |
host |
运行API的主机(主机名或IP地址)。 |
// @host localhost:8080 |
BasePath |
运行API的基本路径。 |
// @BasePath /api/v1 |
accept |
API 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“Mime类型”中所述。 |
// @accept json |
produce |
API可以生成的MIME类型的列表。值必须如“Mime类型”中所述。 |
// @produce json |
query.collection.format |
请求URI query里数组参数的默认格式:csv,multi,pipes,tsv,ssv。 如果未设置,则默认为csv。 |
// @query.collection.format multi |
schemes |
用空格分隔的请求的传输协议。 |
// @schemes http https |
x-name |
扩展的键必须以x-开头,并且只能使用json值 |
// @x-example-key {“key”: “value”} |
使用Markdown描述
如果文档中的短字符串不足以完整表达,或者需要展示图片,代码示例等类似的内容,则可能需要使用Markdown描述。要使用Markdown描述,请使用一下注释。
注释 |
说明 |
示例 |
title |
必填 应用程序的名称。 |
// @title Swagger Example API |
version |
必填 提供应用程序API的版本。 |
// @version 1.0 |
description.markdown |
应用程序的简短描述。 从api.md 文件中解析。 这是@description 的替代用法。 |
// @description.markdown No value needed, this parses the description from api.md |
tag.name |
标签的名称。 |
// @tag.name This is the name of the tag |
tag.description.markdown |
标签说明,这是tag.description 的替代用法。 该描述将从名为tagname.md的 文件中读取。 |
// @tag.description.markdown |
API操作
Example celler/controller
注释 |
描述 |
description |
操作行为的详细说明。 |
description.markdown |
应用程序的简短描述。该描述将从名为endpointname.md 的文件中读取。 |
id |
用于标识操作的唯一字符串。在所有API操作中必须唯一。 |
tags |
每个API操作的标签列表,以逗号分隔。 |
summary |
该操作的简短摘要。 |
accept |
API 可以使用的 MIME 类型列表。 请注意,Accept 仅影响具有请求正文的操作,例如 POST、PUT 和 PATCH。 值必须如“Mime类型”中所述。 |
produce |
API可以生成的MIME类型的列表。值必须如“Mime类型”中所述。 |
param |
用空格分隔的参数。param name ,param type ,data type ,is mandatory? ,comment attribute(optional) |
security |
每个API操作的安全性。 |
success |
以空格分隔的成功响应。return code ,{param type} ,data type ,comment |
failure |
以空格分隔的故障响应。return code ,{param type} ,data type ,comment |
response |
与success、failure作用相同 |
header |
以空格分隔的头字段。 return code ,{param type} ,data type ,comment |
router |
以空格分隔的路径定义。 path ,[httpMethod] |
x-name |
扩展字段必须以x- 开头,并且只能使用json值。 |
Mime类型
swag
接受所有格式正确的MIME类型, 即使匹配 */*
。除此之外,swag
还接受某些MIME类型的别名,如下所示:
Alias |
MIME Type |
json |
application/json |
xml |
text/xml |
plain |
text/plain |
html |
text/html |
mpfd |
multipart/form-data |
x-www-form-urlencoded |
application/x-www-form-urlencoded |
json-api |
application/vnd.api+json |
json-stream |
application/x-json-stream |
octet-stream |
application/octet-stream |
png |
image/png |
jpeg |
image/jpeg |
gif |
image/gif |
参数类型
-
query: 表示带在 url 之后的参数
-
path :表示请求路径上得url变量
-
header : 表示带在 header 信息中得参数
-
body :表示是一个 raw 数据请求,当Accept
是JSON
格式时,我们使用该字段指定接收的JSON类型
-
formData :表示是form表单请求的数据,需要加对应的api注解:// @accept mpfd
,表单数据提交一般不会用于GET
方法,GET
方法常见于url
参数或变量的使用中。
数据类型
- string (string)
- integer (int, uint, uint32, uint64)
- number (float32)
- boolean (bool)
- user defined struct
安全性
注释 |
描述 |
参数 |
示例 |
securitydefinitions.basic |
Basic auth. |
|
// @securityDefinitions.basic BasicAuth |
securitydefinitions.apikey |
API key auth. |
in, name |
// @securityDefinitions.apikey ApiKeyAuth |
securitydefinitions.oauth2.application |
OAuth2 application auth. |
tokenUrl, scope |
// @securitydefinitions.oauth2.application OAuth2Application |
securitydefinitions.oauth2.implicit |
OAuth2 implicit auth. |
authorizationUrl, scope |
// @securitydefinitions.oauth2.implicit OAuth2Implicit |
securitydefinitions.oauth2.password |
OAuth2 password auth. |
tokenUrl, scope |
// @securitydefinitions.oauth2.password OAuth2Password |
securitydefinitions.oauth2.accessCode |
OAuth2 access code auth. |
tokenUrl, authorizationUrl, scope |
// @securitydefinitions.oauth2.accessCode OAuth2AccessCode |
属性
1
2
3
4
5
6
7
8
|
// @Param enumstring query string false "string enums" Enums(A, B, C)
// @Param enumint query int false "int enums" Enums(1, 2, 3)
// @Param enumnumber query number false "int enums" Enums(1.1, 1.2, 1.3)
// @Param string query string false "string valid" minlength(5) maxlength(10)
// @Param int query int false "int valid" minimum(1) maximum(10)
// @Param default query string false "string default" default(A)
// @Param collection query []string false "string collection" collectionFormat(multi)
// @Param extensions query []string false "string collection" extensions(x-example=test,x-nullable)
|
也适用于结构体字段:
1
2
3
4
5
|
type Foo struct {
Bar string `minLength:"4" maxLength:"16"`
Baz int `minimum:"10" maximum:"20" default:"15"`
Qux []string `enums:"foo,bar,baz"`
}
|
当前可用的
进一步的
样例
多行的描述
可以在常规api描述或路由定义中添加跨越多行的描述,如下所示:
1
2
3
|
// @description This is the first line
// @description This is the second line
// @description And so forth.
|
用户自定义的具有数组类型的结构
1
|
// @Success 200 {array} model.Account <-- This is a user defined struct.
|
1
2
3
4
5
6
|
package model
type Account struct {
ID int `json:"id" example:"1"`
Name string `json:"name" example:"account name"`
}
|
响应对象中的模型组合
1
2
|
// JSONResult的data字段类型将被proto.Order类型替换
@success 200 {object} jsonresult.JSONResult{data=proto.Order} "desc"
|
1
2
3
4
5
6
7
8
9
|
type JSONResult struct {
Code int `json:"code" `
Message string `json:"message"`
Data interface{} `json:"data"`
}
type Order struct { //in `proto` package
...
}
|
1
2
3
|
@success 200 {object} jsonresult.JSONResult{data=[]proto.Order} "desc"
@success 200 {object} jsonresult.JSONResult{data=string} "desc"
@success 200 {object} jsonresult.JSONResult{data=[]string} "desc"
|
- 替换多个字段的类型。如果某字段不存在,将添加该字段。
1
|
@success 200 {object} jsonresult.JSONResult{data1=string,data2=[]string,data3=proto.Order,data4=[]proto.Order} "desc"
|
在响应中增加头字段
1
2
3
4
5
6
|
// @Success 200 {string} string "ok"
// @failure 400 {string} string "error"
// @response default {string} string "other error"
// @Header 200 {string} Location "/entity/1"
// @Header 200,400,default {string} Token "token"
// @Header all {string} Token2 "token2"
|
使用多路径参数
1
2
3
4
5
|
/// ...
// @Param group_id path int true "Group ID"
// @Param account_id path int true "Account ID"
// ...
// @Router /examples/groups/{group_id}/accounts/{account_id} [get]
|
结构体的示例值
1
2
3
4
5
|
type Account struct {
ID int `json:"id" example:"1"`
Name string `json:"name" example:"account name"`
PhotoUrls []string `json:"photo_urls" example:"http://test/image/1.jpg,http://test/image/2.jpg"`
}
|
结构体描述
1
2
3
4
5
|
type Account struct {
// ID this is userid
ID int `json:"id"`
Name string `json:"name"` // This is Name
}
|
使用swaggertype
标签更改字段类型
#201
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
type TimestampTime struct {
time.Time
}
///实现encoding.JSON.Marshaler接口
func (t *TimestampTime) MarshalJSON() ([]byte, error) {
bin := make([]byte, 16)
bin = strconv.AppendInt(bin[:0], t.Time.Unix(), 10)
return bin, nil
}
///实现encoding.JSON.Unmarshaler接口
func (t *TimestampTime) UnmarshalJSON(bin []byte) error {
v, err := strconv.ParseInt(string(bin), 10, 64)
if err != nil {
return err
}
t.Time = time.Unix(v, 0)
return nil
}
///
type Account struct {
// 使用`swaggertype`标签将别名类型更改为内置类型integer
ID sql.NullInt64 `json:"id" swaggertype:"integer"`
// 使用`swaggertype`标签更改struct类型为内置类型integer
RegisterTime TimestampTime `json:"register_time" swaggertype:"primitive,integer"`
// Array types can be overridden using "array,<prim_type>" format
Coeffs []big.Float `json:"coeffs" swaggertype:"array,number"`
}
|
#379
1
2
3
4
|
type CerticateKeyPair struct {
Crt []byte `json:"crt" swaggertype:"string" format:"base64" example:"U3dhZ2dlciByb2Nrcw=="`
Key []byte `json:"key" swaggertype:"string" format:"base64" example:"U3dhZ2dlciByb2Nrcw=="`
}
|
生成的swagger文档如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
"api.MyBinding": {
"type":"object",
"properties":{
"crt":{
"type":"string",
"format":"base64",
"example":"U3dhZ2dlciByb2Nrcw=="
},
"key":{
"type":"string",
"format":"base64",
"example":"U3dhZ2dlciByb2Nrcw=="
}
}
}
|
使用swaggerignore
标签排除字段
1
2
3
4
5
|
type Account struct {
ID string `json:"id"`
Name string `json:"name"`
Ignored int `swaggerignore:"true"`
}
|
将扩展信息添加到结构字段
1
2
3
|
type Account struct {
ID string `json:"id" extensions:"x-nullable,x-abc=def,!x-omitempty"` // 扩展字段必须以"x-"开头
}
|
生成swagger文档,如下所示:
1
2
3
4
5
6
7
8
9
10
11
|
"Account": {
"type": "object",
"properties": {
"id": {
"type": "string",
"x-nullable": true,
"x-abc": "def",
"x-omitempty": false
}
}
}
|
对展示的模型重命名
1
2
3
|
type Resp struct {
Code int
}//@name Response
|
如何使用安全性注释
通用API信息。
1
2
3
4
5
6
|
// @securityDefinitions.basic BasicAuth
// @securitydefinitions.oauth2.application OAuth2Application
// @tokenUrl https://example.com/oauth/token
// @scope.write Grants write access
// @scope.admin Grants read and write access to administrative information
|
每个API操作。
1
|
// @Security ApiKeyAuth
|
使用AND条件。
1
2
|
// @Security ApiKeyAuth
// @Security OAuth2Application[write, admin]
|
token
的api注解
swagger除了可以查看文档外,还可以直接try it out
调用接口,有些接口是需要登录后才能调用。有个token鉴权。
校验token 的api接口 header中必须有正确的 Authorization
可以通过添加通用的API注释来设置全局接口的header值
1
2
3
4
5
|
// @securityDefinitions.apikey CoreAPI
// @name Authorization
// @in header
//设置header字段 Authorization
|
然后在需要token接口注释上增加
1
2
|
// @Security CoreAPI
//并且需要携带对应的token,一般token放在Bear开头,所以需要如下图操作:(Bear{token},注意两者之间有空格)
|