swaggo使用详解

1. 简介:

swagger是一套基于OpenAPI规范构建的开源工具,使用RestApi。swagger-ui 呈现出来的是一份可交互式的API文档,可以直接在文档页面尝试API的调用。
gin-swagger 是基于注释生成 API 文档,项目地址:https://github.com/swaggo/swag

2. 安装swag

//go版本1.16之前使用该命令
go get -u github.com/swaggo/swag/cmd/swag

//go版本1.16版本以及之后的版本使用该命令
go install github.com/swaggo/swag/cmd/swag@latest

3. swag命令

swag -h
swag init -h

4. 与gin集成

项目目录结构:

4.1 在main.go代码中添加通用API注释:

点击查看代码
package main

import (
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
	//"github.com/swaggo/swag/example/celler/controller"

	"swag_test01/controller"
	"swag_test01/docs"
)

//go:generate swag init --parseDependency --parseInternal --parseDepth 6

// @title go-admin API
// @version 2.0.0
// @description 基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档
// @description 添加qq群: 521386980 进入技术交流群 请先star,谢谢!
// @license.name MIT
// @license.url https://github.com/go-admin-team/go-admin/blob/master/LICENSE.md

// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization

func main() {
        // 动态设置一些通用API信息
	docs.SwaggerInfo.Title = "Swagger example API"
	docs.SwaggerInfo.Description = "基于Gin + Vue + Element UI的前后端分离权限管理系统的接口文档"
	docs.SwaggerInfo.Version = "2.0"
	docs.SwaggerInfo.Host = "127.0.0.1:8080"
	docs.SwaggerInfo.BasePath = "/api/v1"
	docs.SwaggerInfo.Schemes = []string{"http", "https"}

	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")
}

4.2 在 controller/accounts.go代码中添加API操作注释
点击查看代码
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)
}

// AddAccount godoc
//
//	@Summary		Add an account
//	@Description	add by json account
//	@Tags			accounts
//	@Accept			json
//	@Produce		json
//	@Param			account	body		model.AddAccount	true	"Add account"
//	@Success		200		{object}	model.Account
//	@Failure		400		{object}	httputil.HTTPError
//	@Failure		404		{object}	httputil.HTTPError
//	@Failure		500		{object}	httputil.HTTPError
//	@Router			/accounts [post]
func (c *Controller) AddAccount(ctx *gin.Context) {
	var addAccount model.AddAccount
	if err := ctx.ShouldBindJSON(&addAccount); err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	if err := addAccount.Validation(); err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	account := model.Account{
		Name: addAccount.Name,
	}
	lastID, err := account.Insert()
	if err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	account.ID = lastID
	ctx.JSON(http.StatusOK, account)
}

// UpdateAccount godoc
//
//	@Summary		Update an account
//	@Description	Update by json account
//	@Tags			accounts
//	@Accept			json
//	@Produce		json
//	@Param			id		path		int					true	"Account ID"
//	@Param			account	body		model.UpdateAccount	true	"Update account"
//	@Success		200		{object}	model.Account
//	@Failure		400		{object}	httputil.HTTPError
//	@Failure		404		{object}	httputil.HTTPError
//	@Failure		500		{object}	httputil.HTTPError
//	@Router			/accounts/{id} [patch]
func (c *Controller) UpdateAccount(ctx *gin.Context) {
	id := ctx.Param("id")
	aid, err := strconv.Atoi(id)
	if err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	var updateAccount model.UpdateAccount
	if err := ctx.ShouldBindJSON(&updateAccount); err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	account := model.Account{
		ID:   aid,
		Name: updateAccount.Name,
	}
	err = account.Update()
	if err != nil {
		httputil.NewError(ctx, http.StatusNotFound, err)
		return
	}
	ctx.JSON(http.StatusOK, account)
}

// DeleteAccount godoc
//
//	@Summary		Delete an account
//	@Description	Delete by account ID
//	@Tags			accounts
//	@Accept			json
//	@Produce		json
//	@Param			id	path		int	true	"Account ID"	Format(int64)
//	@Success		204	{object}	model.Account
//	@Failure		400	{object}	httputil.HTTPError
//	@Failure		404	{object}	httputil.HTTPError
//	@Failure		500	{object}	httputil.HTTPError
//	@Router			/accounts/{id} [delete]
func (c *Controller) DeleteAccount(ctx *gin.Context) {
	id := ctx.Param("id")
	aid, err := strconv.Atoi(id)
	if err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	err = model.Delete(aid)
	if err != nil {
		httputil.NewError(ctx, http.StatusNotFound, err)
		return
	}
	ctx.JSON(http.StatusNoContent, gin.H{})
}

// UploadAccountImage godoc
//
//	@Summary		Upload account image
//	@Description	Upload file
//	@Tags			accounts
//	@Accept			multipart/form-data
//	@Produce		json
//	@Param			id		path		int		true	"Account ID"
//	@Param			file	formData	file	true	"account image"
//	@Success		200		{object}	controller.Message
//	@Failure		400		{object}	httputil.HTTPError
//	@Failure		404		{object}	httputil.HTTPError
//	@Failure		500		{object}	httputil.HTTPError
//	@Router			/accounts/{id}/images [post]
func (c *Controller) UploadAccountImage(ctx *gin.Context) {
	id, err := strconv.Atoi(ctx.Param("id"))
	if err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	file, err := ctx.FormFile("file")
	if err != nil {
		httputil.NewError(ctx, http.StatusBadRequest, err)
		return
	}
	ctx.JSON(http.StatusOK, Message{Message: fmt.Sprintf("upload complete userID=%d filename=%s", id, file.Filename)})
}


// Controller example
type Controller struct {
}

// NewController example
func NewController() *Controller {
	return &Controller{}
}

// Message example
type Message struct {
	Message string `json:"message" example:"message"`
}

4.3 httputil/error.go

package httputil

import (
	"github.com/gin-gonic/gin"
)

// NewError example
func NewError(ctx *gin.Context, status int, err error) {
	er := HTTPError{
		Code:    status,
		Message: err.Error(),
	}
	ctx.JSON(status, er)
}

// HTTPError example
type HTTPError struct {
	Code    int    `json:"code" example:"400"`
	Message string `json:"message" example:"status bad request"`
}

4.4 model/account.go

点击查看代码
package model

import (
	"errors"
	"fmt"

	uuid "github.com/gofrs/uuid"
)

// Account example
type Account struct {
	ID   int       `json:"id" example:"1" format:"int64"`
	Name string    `json:"name" example:"account name"`
	UUID uuid.UUID `json:"uuid" example:"550e8400-e29b-41d4-a716-446655440000" format:"uuid"`
}

// example
var (
	ErrNameInvalid = errors.New("name is empty")
)

// AddAccount example
type AddAccount struct {
	Name string `json:"name" example:"account name"`
}

// Validation example
func (a AddAccount) Validation() error {
	switch {
	case len(a.Name) == 0:
		return ErrNameInvalid
	default:
		return nil
	}
}

// UpdateAccount example
type UpdateAccount struct {
	Name string `json:"name" example:"account name"`
}

// Validation example
func (a UpdateAccount) Validation() error {
	switch {
	case len(a.Name) == 0:
		return ErrNameInvalid
	default:
		return nil
	}
}

// AccountsAll example
func AccountsAll(q string) ([]Account, error) {
	if q == "" {
		return accounts, nil
	}
	as := []Account{}
	for k, v := range accounts {
		if q == v.Name {
			as = append(as, accounts[k])
		}
	}
	return as, nil
}

// AccountOne example
func AccountOne(id int) (Account, error) {
	for _, v := range accounts {
		if id == v.ID {
			return v, nil
		}
	}
	return Account{}, ErrNoRow
}

// Insert example
func (a Account) Insert() (int, error) {
	accountMaxID++
	a.ID = accountMaxID
	a.Name = fmt.Sprintf("account_%d", accountMaxID)
	accounts = append(accounts, a)
	return accountMaxID, nil
}

// Delete example
func Delete(id int) error {
	for k, v := range accounts {
		if id == v.ID {
			accounts = append(accounts[:k], accounts[k+1:]...)
			return nil
		}
	}
	return fmt.Errorf("account id=%d is not found", id)
}

// Update example
func (a Account) Update() error {
	for k, v := range accounts {
		if a.ID == v.ID {
			accounts[k].Name = a.Name
			return nil
		}
	}
	return fmt.Errorf("account id=%d is not found", a.ID)
}

var accountMaxID = 3
var accounts = []Account{
	{ID: 1, Name: "account_1"},
	{ID: 2, Name: "account_2"},
	{ID: 3, Name: "account_3"},
}

4.5 model/error.go

package model

import "errors"

var (
	// ErrNoRow example
	ErrNoRow = errors.New("no rows in result set")
)

生成文档

swag init
运行程序,然后浏览器访问http://localhost:8080/swagger/index.html 。将看到Swagger 2.0 Api文档,如下所示:

5. 格式化工具

可以针对Swag的注释自动格式化,就像go fmt命令一样。
用法:
swag fmt
排除路径:
swag fmt -d ./ --exclude ./internal
使用swag fmt时,为了确保格式正确,需要保证为函数提供文档注释。这是由于swag fmt只允许在标准文档注释之后使用tabs缩进。
例如:

// 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) {

通用API注释

注释 说明 示例
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仅影响具有body的请求,例如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

使用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操作注释

注释 说明
description 操作行为的详细说明
description.markdown 应用程序的简短描述。会从文件中读取描述。例如@description.markdown details将加载details.md
id 用于标识API操作的唯一字符串。在所有API操作中必须是唯一的
tags API所属的标签列表,用逗号分隔
summary 操作的简短摘要
accept API可以使用的MIME类型列表。注意,Accept仅影响具有body的请求,例如POST、PUT和PATCH。值必须是Mime类型中的一种
produce API可以生成的MIME类型列表.。值必须是Mime类型中的一种
param 以空格分隔的参数。 参数名, 参数类型, 数据类型, 是否强制, "注释", 属性(可选)
security API操作的安全性
success 以空格分隔的成功响应。 状态码, {参数类型}, 数据类型,"注释" , 注意这里的参数类型和 @param的参数类型不同,这里和数据类型有点相似,可以取值 {string}, {array}, {object}等 ,同时不要忘记要带一对花括号
failure 以空格分隔的失败响应。 状态码, {参数类型}, 数据类型,"注释" , 注意这里的参数类型和 @param的参数类型不同,这里和数据类型有点相似,可以取值 {string}, {array}, {object}等 ,同时不要忘记要带一对花括号
response 和 success 、failure用法相同
header 以空格分隔的头字段。 状态码, {参数类型}, header键值, "注释" , 注意这里的参数类型和 @param的参数类型不同,这里和数据类型有点相似,可以取值 {string}, {array}, {object}等 ,同时不要忘记要带一对花括号
router 以空格分隔的路径定义。 path,[httpMethod]
x-name 扩字段必须以x-开头,并且只能接受json值
x-codeSample 可选的Markdown用法。将“file”作为参数。然后会在给定文件夹中搜索类似summary的文件
deprecated 标记API为废弃状态

MIME类型

swag 接受所有格式正确的MIME类型,即匹配 /。
另外,swag也会接收一些如下所示的别名:

别名 MIME 类型
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
  • path
  • header
  • body
  • formData

数据类型

  • string (string)
  • integer (int, uint, uint32, uint64)
  • number (float32)
  • boolean (bool)
  • user defined struct

安全性

annotation description parameters example
securitydefinitions.basic Basic auth. // @securityDefinitions.basic BasicAuth
securitydefinitions.apikey API key auth. in, name, description // @securityDefinitions.apikey ApiKeyAuth
securitydefinitions.oauth2.application OAuth2 application auth. tokenUrl, scope, description // @securitydefinitions.oauth2.application OAuth2Application
securitydefinitions.oauth2.implicit OAuth2 implicit auth. authorizationUrl, scope, description // @securitydefinitions.oauth2.implicit OAuth2Implicit
securitydefinitions.oauth2.password OAuth2 password auth. tokenUrl, scope, description // @securitydefinitions.oauth2.password OAuth2Password
securitydefinitions.oauth2.accessCode OAuth2 access code auth. tokenUrl, authorizationUrl, scope, description // @securitydefinitions.oauth2.accessCode OAuth2AccessCode
parameters annotation example
in // @in header
name // @name Authorization
tokenUrl // @tokenUrl https://example.com/oauth/token
authorizationurl // @authorizationurl https://example.com/oauth/authorize
scope.hoge // @scope.write Grants write access
description // @description OAuth protects our entity endpoints

属性

// @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   example     query     string     false  "string example"     example(string)
// @Param   collection  query     []string   false  "string collection"  collectionFormat(multi)
// @Param   extensions  query     []string   false  "string collection"  extensions(x-example=test,x-nullable)

也适用于结构体字段

type Foo struct {
    Bar string `minLength:"4" maxLength:"16" example:"random string"`
    Baz int `minimum:"10" maximum:"20" default:"15"`
    Qux []string `enums:"foo,bar,baz"`
}

可用属性

11 示例:

11.1 多行的描述

可以在常规api描述或路由定义中添加跨越多行的描述,如下所示:

// @description This is the first line
// @description This is the second line
// @description And so forth.
11.2 用户自定义的具有数组类型的结构

// @Success 200 {array} model.Account <-- This is a user defined struct.

package model
type Account struct {
    ID   int    `json:"id" example:"1"`
    Name string `json:"name" example:"account name"`
}
11.3 函数作用域结构声明

可以在函数体中声明请求响应结构体。You can declare your request response structs inside a function body。
必须遵循命名约定<包名>.<函数名>.<结构体名称>。

package main
// @Param request body main.MyHandler.request true "query params"
// @Success 200 {object} main.MyHandler.response
// @Router /test [post]
func MyHandler() {
	type request struct {
		RequestField string
	}
	type response struct {
		ResponseField string
	}
}
11.4 响应对象中的模型组合
// JSONResult's data field will be overridden by the specific type proto.Order
@success 200 {object} jsonresult.JSONResult{data=proto.Order} "desc"
type JSONResult struct {
    Code    int          `json:"code" `
    Message string       `json:"message"`
    Data    interface{}  `json:"data"`
}
type Order struct { //in `proto` package
    Id  uint            `json:"id"`
    Data  interface{}   `json:"data"`
}

还支持对象数组和原始类型作为嵌套响应。

@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"

替换多个字段的类型。如果某字段不存在,将添加该字段。

@success 200 {object} jsonresult.JSONResult{data1=string,data2=[]string,data3=proto.Order,data4=[]proto.Order} "desc"

覆盖深层字段

type DeepObject struct { //in `proto` package
	...
}
@success 200 {object} jsonresult.JSONResult{data1=proto.Order{data=proto.DeepObject},data2=[]proto.Order{data=[]proto.DeepObject}} "desc"

11.5 在响应中增加头字段
// @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"
11.6 使用多路径参数
/// ...
// @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]
11.7 添加多路径
/// ...
// @Param group_id path int true "Group ID"
// @Param user_id  path int true "User ID"
// ...
// @Router /examples/groups/{group_id}/user/{user_id}/address [put]
// @Router /examples/user/{user_id}/address [put]
11.8 结构体的示例值
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"`
}
11.9 body的SchemaExample
// @Param email body string true "message/rfc822" SchemaExample(Subject: Testmail\r\n\r\nBody Message\r\n)
11.10 结构体描述
// Account model info
// @Description User account information
// @Description with user id and username
type Account struct {
	// ID this is userid
	ID   int    `json:"id"`
	Name string `json:"name"` // This is Name
}

708解析器只处理以@Description属性开头的结构注释。

但它会按原样写入所有结构字段注释。
因此,生成的swagger文档如下:

"Account": {
  "type":"object",
  "description": "User account information with user id and username"
  "properties": {
    "id": {
      "type": "integer",
      "description": "ID this is userid"
    },
    "name": {
      "type":"string",
      "description": "This is Name"
    }
  }
}
3.11 使用swaggertype标签更改字段类型
type TimestampTime struct {
    time.Time
}
///implement encoding.JSON.Marshaler interface
func (t *TimestampTime) MarshalJSON() ([]byte, error) {
    bin := make([]byte, 16)
    bin = strconv.AppendInt(bin[:0], t.Time.Unix(), 10)
    return bin, nil
}
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 {
    // Override primitive type by simply specifying it via `swaggertype` tag
    ID     sql.NullInt64 `json:"id" swaggertype:"integer"`
    // Override struct type to a primitive type 'integer' by specifying it via `swaggertype` tag
    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"`
}

示例:

type CerticateKeyPair struct {
	Crt []byte `json:"crt" swaggertype:"string" format:"base64" example:"U3dhZ2dlciByb2Nrcw=="`
	Key []byte `json:"key" swaggertype:"string" format:"base64" example:"U3dhZ2dlciByb2Nrcw=="`
}

生成的swagger文档如下:

"api.MyBinding": {
  "type":"object",
  "properties":{
    "crt":{
      "type":"string",
      "format":"base64",
      "example":"U3dhZ2dlciByb2Nrcw=="
    },
    "key":{
      "type":"string",
      "format":"base64",
      "example":"U3dhZ2dlciByb2Nrcw=="
    }
  }
}
使用全局重写来支持自定义类型

如果您使用的是生成的文件,可能无法使用swaggertype标记以支持自定义类型,或swaggerignore标记。
通过使用--overridesFile传递映射到swag,可以在任何地方使用一种类型代替另一种类型。默认情况下,如果当前目录中存在“.swaggo”文件,则将使用该文件。
Go代码:

type MyStruct struct {
  ID     sql.NullInt64 `json:"id"`
  Name   sql.NullString `json:"name"`
}

.swaggo:

// Replace all NullInt64 with int
replace database/sql.NullInt64 int
// Don't include any fields of type database/sql.NullString in the swagger docs
skip    database/sql.NullString

指令的具体含义在注释(以“//”开头)注明了、“replace path/to/a.type path/to/b.type”和“skip path/to/a.type”。
(请注意,必须提供指向任何命名类型的完整路径,以防止在多个包定义具有相同名称的类型时出现问题)。
提供:

"types.MyStruct": {
  "id": "integer"
}
3.12 使用swaggerignore标签排除字段
type Account struct {
    ID   string    `json:"id"`
    Name string     `json:"name"`
    Ignored int     `swaggerignore:"true"`
}
3.13 将扩展信息添加到结构字段
type Account struct {
    ID   string    `json:"id"   extensions:"x-nullable,x-abc=def,!x-omitempty"` // extensions fields must start with "x-"
}

生成的swagger文档如下:

"Account": {
    "type": "object",
    "properties": {
        "id": {
            "type": "string",
            "x-nullable": true,
            "x-abc": "def",
            "x-omitempty": false
        }
    }
}
3.14 对展示的模型重命名
type Resp struct {
	Code int
}//@name Response
3.15 如何使用安全性注释

通用API信息

// @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操作
// @Security ApiKeyAuth
使用AND条件

// @Security ApiKeyAuth
// @Security OAuth2Application[write, admin]

使用OR条件

// @Security ApiKeyAuth || firebase
// @Security OAuth2Application[write, admin] || APIKeyAuth
3.16 添加枚举项的说明
type Example struct {
	// Sort order:
	// * asc - Ascending, from A to Z.
	// * desc - Descending, from Z to A.
	Order string `enums:"asc,desc"`
}
3.17 仅生成特定的文档文件类型

默认情况下,swag命令使用如下三种不同的文件生成Swagger规范:

  • docs.go
  • swagger.json
  • swagger.yaml
    如果要限制应生成的一组文件类型,可以使用--outputTypes(-ot)标志。默认值为go,json,yaml-输出类型用逗号分隔。要将输出限制为go和yaml文件,可以编写go,yaml。使用完整的命令swag init--outputTypes go,yaml。

参考文档
github源码

posted @ 2023-02-06 17:26  专职  阅读(2409)  评论(0编辑  收藏  举报