Swagger是一個簡單但功能強大的API表達工具。它具備地球上最大的API工具生態系統,數以千計的開發人員,使用幾乎全部的現代編程語言,都在支持和使用Swagger。使用Swagger生成API,咱們能夠獲得交互式文檔,自動生成代碼的SDK以及API的發現特性等。html
一個最簡單的swagger文檔示例:git
swagger: "2.0"
info:
version: 1.0.0
title: Simple API
description: A simple API to learn how to write OpenAPI Specification
schemes:
- https
host: simple.api
basePath: /openapi101
paths: {}
複製代碼
Tips:閱讀本文前提是假設你已經瞭解瞭如何編寫swagger文檔,固然,若是還不瞭解也不要緊,能夠去swagger官網查看文檔進行學習,而且這裏還有一套《Swagger從入門到精通》附上.程序員
寫做本文的緣由是由於公司要求api文檔都使用 swagger格式,項目是用golang編寫的,做爲一個懶癌程序員,怎麼可以忍受去編寫這麼複雜的swagger文檔呢?有沒有一鍵生成的工具呢?google一下,還真有,那就是go-swagger項目。go-swagger衆多特點功能之一就是Generate a spec from source,即經過源碼生成文檔,很符合個人需求。github
下面就簡單介紹下如何爲項目加上swagger註釋,而後一鍵生成API文檔golang
開始以前須要安裝兩個工具:docker
安裝swagger-editor,我這裏使用docker運行,其餘安裝方式,請查看官方文檔:shell
docker pull swaggerapi/swagger-editor
docker run --rm -p 80:8080 swaggerapi/swagger-editor
複製代碼
安裝go-swagger,我這邊使用brew安裝,其餘安裝方式,請查看官方文檔編程
brew tap go-swagger/go-swagger
brew install go-swagger
複製代碼
好了,如今終於開始正題:start coding!!!json
1.假設有一個user.server,提供一些REST API,用於對用戶數據的增刪改查。api
好比這裏有一個getOneUser
接口,是查詢用戶信息的:
package service
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"user.server/models"
"github.com/Sirupsen/logrus"
)
type GetUserParam struct {
Id int `json:"id"`
}
func GetOneUser(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
decoder := json.NewDecoder(r.Body)
var param GetUserParam
err := decoder.Decode(¶m)
if err != nil {
WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)
return
}
// get user from db
user, err := models.GetOne(strconv.Itoa(param.Id))
if err != nil {
logrus.Warn(err)
WriteResponse(w, ErrorResponseCode, "failed", nil)
return
}
WriteResponse(w, SuccessResponseCode, "success", user)
}
複製代碼
根據swagger文檔規範,一個swagger文檔首先要有swagger的版本和info信息。利用go-swagger只須要在聲明package以前加上以下注釋便可:
// Package classification User API.
//
// The purpose of this service is to provide an application
// that is using plain go code to define an API
//
// Host: localhost
// Version: 0.0.1
//
// swagger:meta
package service
複製代碼
而後在項目根目錄下使用swagger generate spec -o ./swagger.json
命令生成swagger.json
文件:
此命令會找到main.go入口文件,而後遍歷全部源碼文件,解析而後生成swagger.json文件
{
"swagger": "2.0",
"info": {
"description": "The purpose of this service is to provide an application\nthat is using plain go code to define an API",
"title": "User API.",
"version": "0.0.1"
},
"host": "localhost",
"paths": {}
}
複製代碼
2.基本信息有了,而後就要有路由,請求,響應等,下面針對getOneUser接口編寫swagger註釋:
// swagger:parameters getSingleUser
type GetUserParam struct {
// an id of user info
//
// Required: true
// in: path
Id int `json:"id"`
}
func GetOneUser(w http.ResponseWriter, r *http.Request) {
// swagger:route GET /users/{id} users getSingleUser
//
// get a user by userID
//
// This will show a user info
//
// Responses:
// 200: UserResponse
decoder := json.NewDecoder(r.Body)
var param GetUserParam
err := decoder.Decode(¶m)
if err != nil {
WriteResponse(w, ErrorResponseCode, "request param is invalid, please check!", nil)
return
}
// get user from db
user, err := models.GetOne(strconv.Itoa(param.Id))
if err != nil {
logrus.Warn(err)
WriteResponse(w, ErrorResponseCode, "failed", nil)
return
}
WriteResponse(w, SuccessResponseCode, "success", user)
}
複製代碼
能夠看到在GetUserParam
結構體上面加了一行swagger:parameters getSingleUser
的註釋信息,這是聲明接口的入參註釋,結構體內部的幾行註釋指明瞭id這個參數必填,而且查詢參數id是在url path中。詳細用法,參考: swagger:params
在GetOneUser
函數中:
swagger:route
指明使用的http method,路由,以及標籤和operation id,詳細用法,參考: swagger:routeResponses
指明瞭返回值的code以及類型而後再聲明響應:
// User Info
//
// swagger:response UserResponse
type UserWapper struct {
// in: body
Body ResponseMessage
}
type ResponseMessage struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
複製代碼
使用swagger:response
語法聲明返回值,其上兩行是返回值的描述(我也不清楚,爲啥描述信息要寫在上面,歡迎解惑),詳細用法,參考; swagger:response
而後瀏覽器訪問localhost
,查看swagger-editor界面,點擊工具欄中的File->Impoprt File
上傳剛纔生成的 swagger.json
文件,就能夠看到界面:
這樣一個簡單的api文檔就生成了
3.怎麼樣?是否是很簡單?但是又感受那裏不對,嗯,註釋都寫在代碼裏了,很不美觀,並且不易維護。想一下go-swagger的原理是掃描目錄下的全部go文件,解析註釋信息。那麼是否是能夠把api註釋都集中寫在單個文件內,統一管理,省得分散在各個源碼文件內。
新建一個doc.go
文件,這裏還有一個接口是UpdateUser
,那麼咱們在doc.go文件中聲明此接口的api註釋。先看一下UpdateUser
接口的代碼:
func UpdateUser(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
// decode body data into user struct
decoder := json.NewDecoder(r.Body)
user := models.User{}
err := decoder.Decode(&user)
if err != nil {
WriteResponse(w, ErrorResponseCode, "user data is invalid, please check!", nil)
return
}
// check if user exists
data, err := models.GetUserById(user.Id)
if err != nil {
logrus.Warn(err)
WriteResponse(w, ErrorResponseCode, "query user failed", nil)
return
}
if data.Id == 0 {
WriteResponse(w, ErrorResponseCode, "user not exists, no need to update", nil)
return
}
// update
_, err = models.Update(user)
if err != nil {
WriteResponse(w, ErrorResponseCode, "update user data failed, please try again!", nil)
return
}
WriteResponse(w, SuccessResponseCode, "update user data success!", nil)
}
複製代碼
而後再doc.go文件中編寫以下聲明:
package service
import "user.server/models"
// swagger:parameters UpdateUserResponseWrapper
type UpdateUserRequest struct {
// in: body
Body models.User
}
// Update User Info
//
// swagger:response UpdateUserResponseWrapper
type UpdateUserResponseWrapper struct {
// in: body
Body ResponseMessage
}
// swagger:route POST /users users UpdateUserResponseWrapper
//
// Update User
//
// This will update user info
//
// Responses:
// 200: UpdateUserResponseWrapper
複製代碼
這樣就把api聲明註釋給抽離出來了,而後使用命令swagger generate spec -o ./swagger.json
生成json文件,就能夠看到這樣的結果:
很簡單吧,參照文檔編寫幾行註釋,而後一個命令生成API文檔。懶癌程序員福音~
參考: