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文档。懒癌程序员福音~
参考: