swagger2版本文档解析1.0版本 #2
167
common.go
Normal file
167
common.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// Package api_doc ...
|
||||||
|
//
|
||||||
|
// Description : api_doc ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2024-12-24 10:52
|
||||||
|
package api_doc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"git.zhangdeman.cn/gateway/api-doc/define"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/consts"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetUriPathParamList 获取uri参数列表
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 10:52 2024/12/24
|
||||||
|
func GetUriPathParamList(uriPath string) []*define.ParamConfig {
|
||||||
|
var (
|
||||||
|
paramList []string
|
||||||
|
result = make([]*define.ParamConfig, 0)
|
||||||
|
)
|
||||||
|
if paramList = define.UriParamRegexp.FindAllString(uriPath, -1); len(paramList) == 0 {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
for _, param := range paramList {
|
||||||
|
result = append(result, &define.ParamConfig{
|
||||||
|
Location: consts.RequestDataLocationUriPath.String(),
|
||||||
|
Path: strings.TrimRight(strings.TrimLeft(param, "{"), "}"),
|
||||||
|
Type: consts.DataTypeString.String(),
|
||||||
|
Title: param,
|
||||||
|
Description: param,
|
||||||
|
Required: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDataType 将文档配置的数据类型转换为归一化处理后的数据类型
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 11:52 2024/12/24
|
||||||
|
func GetDataType(docParamType string, formatType string) consts.DataType {
|
||||||
|
docParamType = strings.ToLower(docParamType)
|
||||||
|
formatType = strings.ToLower(formatType)
|
||||||
|
if len(formatType) == 0 {
|
||||||
|
formatType = docParamType
|
||||||
|
}
|
||||||
|
switch docParamType {
|
||||||
|
case "integer":
|
||||||
|
if formatType == "int64" {
|
||||||
|
return consts.DataTypeInt
|
||||||
|
}
|
||||||
|
return consts.DataTypeUint
|
||||||
|
case "string", "apikey":
|
||||||
|
return consts.DataTypeString
|
||||||
|
case "object":
|
||||||
|
return consts.DataTypeMapStrAny
|
||||||
|
case "boolean":
|
||||||
|
return consts.DataTypeBool
|
||||||
|
case "number", "float", "double", "float32", "float64":
|
||||||
|
return consts.DataTypeFloat
|
||||||
|
case "array":
|
||||||
|
if formatType == "integer" {
|
||||||
|
return consts.DataTypeSliceInt
|
||||||
|
} else if formatType == "string" {
|
||||||
|
return consts.DataTypeSliceString
|
||||||
|
} else {
|
||||||
|
return consts.DataTypeSliceAny
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return consts.DataTypeAny
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParamLocation 获取参数位置
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 12:02 2024/12/24
|
||||||
|
func GetParamLocation(docParamLocation string) consts.RequestDataLocation {
|
||||||
|
docParamLocation = strings.ToLower(docParamLocation)
|
||||||
|
switch docParamLocation {
|
||||||
|
case "query":
|
||||||
|
return consts.RequestDataLocationQuery
|
||||||
|
case "header":
|
||||||
|
return consts.RequestDataLocationHeader
|
||||||
|
case "cookie":
|
||||||
|
return consts.RequestDataLocationCookie
|
||||||
|
case "body":
|
||||||
|
return consts.RequestDataLocationBody
|
||||||
|
case "path":
|
||||||
|
return consts.RequestDataLocationUriPath
|
||||||
|
default:
|
||||||
|
return consts.RequestDataLocationQuery
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRealDefinitionsKey 通过schema下的 $ref 获取真实的 definitions key
|
||||||
|
func GetRealDefinitionsKey(ref string) string {
|
||||||
|
return strings.TrimPrefix(ref, "#/definitions/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRealResponseKey 通过schema下的 $ref 获取真实的 response key
|
||||||
|
func GetRealResponseKey(ref string) string {
|
||||||
|
return strings.TrimPrefix(ref, "#/responses/")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSuccessResponseConfig 获取成功的响应配置
|
||||||
|
func GetSuccessResponseConfig(resultConfig map[string]*define.SwaggerPathConfigResponse) *define.SwaggerPathConfigResponse {
|
||||||
|
for httpCode := 200; httpCode <= 299; httpCode++ {
|
||||||
|
if cfg := resultConfig[fmt.Sprintf("%d", httpCode)]; nil != cfg {
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataTypeIsArray 判断数据类型是否为数组
|
||||||
|
func DataTypeIsArray(docDataType string) bool {
|
||||||
|
return strings.ToLower(docDataType) == "array"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandArrayParam 展开详细的数组配置
|
||||||
|
func ExpandArrayParam(swaggerDoc *define.Swagger, ref string, rootPath string) []*define.ParamConfig {
|
||||||
|
pathPrefix := ""
|
||||||
|
if len(rootPath) > 0 {
|
||||||
|
pathPrefix = rootPath + "."
|
||||||
|
}
|
||||||
|
res := make([]*define.ParamConfig, 0)
|
||||||
|
for itemKey, itemConfig := range swaggerDoc.Definitions[GetRealDefinitionsKey(ref)].Properties {
|
||||||
|
res = append(res, &define.ParamConfig{
|
||||||
|
Location: consts.RequestDataLocationBody.String(),
|
||||||
|
Path: pathPrefix + "{{#idx#}}." + itemKey,
|
||||||
|
Type: GetDataType(itemConfig.Type, "").String(),
|
||||||
|
Title: pathPrefix + itemKey,
|
||||||
|
Description: pathPrefix + itemKey,
|
||||||
|
Required: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpandArrayResult 展开返回值配置
|
||||||
|
func ExpandArrayResult(swaggerDoc *define.Swagger, ref string, rootPath string) []*define.ResultConfig {
|
||||||
|
pathPrefix := ""
|
||||||
|
if len(rootPath) > 0 && rootPath != consts.ResponseDataLocationBodyRoot.String() {
|
||||||
|
pathPrefix = rootPath + "."
|
||||||
|
}
|
||||||
|
ref = GetRealDefinitionsKey(ref)
|
||||||
|
res := make([]*define.ResultConfig, 0)
|
||||||
|
for itemKey, itemConfig := range swaggerDoc.Definitions[ref].Properties {
|
||||||
|
res = append(res, &define.ResultConfig{
|
||||||
|
Location: consts.ResponseDataLocationBody.String(),
|
||||||
|
Path: pathPrefix + "{{#idx#}}." + itemKey,
|
||||||
|
Type: GetDataType(itemConfig.Type, "").String(),
|
||||||
|
Title: pathPrefix + itemKey,
|
||||||
|
Description: pathPrefix + itemKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
@ -7,6 +7,21 @@
|
|||||||
// Date : 2024-08-14 15:20
|
// Date : 2024-08-14 15:20
|
||||||
package define
|
package define
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
// DocParseResult 文档解析结果
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 10:30 2024/12/24
|
||||||
|
type DocParseResult struct {
|
||||||
|
Domain string `json:"domain"` // 域名
|
||||||
|
Title string `json:"title"` // 标题
|
||||||
|
Description string `json:"description"` // 描述
|
||||||
|
UriList []*UriBaseConfig `json:"uri_list"` // 接口列表
|
||||||
|
GlobalSecurityParamList []*ParamConfig `json:"global_security_param_list"` // 全局安全类参数配置
|
||||||
|
}
|
||||||
|
|
||||||
// UriBaseConfig 添加接口时的基础配置
|
// UriBaseConfig 添加接口时的基础配置
|
||||||
//
|
//
|
||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
@ -16,9 +31,12 @@ type UriBaseConfig struct {
|
|||||||
Uri string `json:"uri"` // 接口路由
|
Uri string `json:"uri"` // 接口路由
|
||||||
Method string `json:"method"` // 接口请求方法
|
Method string `json:"method"` // 接口请求方法
|
||||||
ContentType string `json:"content_type"` // 接口请求类型
|
ContentType string `json:"content_type"` // 接口请求类型
|
||||||
|
OutputContentType string `json:"output_content_type"` // 输出数据类型
|
||||||
TagList []string `json:"tag_list"` // 接口标签列表
|
TagList []string `json:"tag_list"` // 接口标签列表
|
||||||
Summary string `json:"summary"` // 接口摘要描述
|
Summary string `json:"summary"` // 接口摘要描述
|
||||||
Description string `json:"description"` // 接口详细描述
|
Description string `json:"description"` // 接口详细描述
|
||||||
|
ParamList []*ParamConfig `json:"param_list"` // 参数列表
|
||||||
|
ResultList []*ResultConfig `json:"result_list"` // 返回值列表
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParamConfig 参数配置
|
// ParamConfig 参数配置
|
||||||
@ -32,6 +50,7 @@ type ParamConfig struct {
|
|||||||
Type string `json:"type"` // 参数类型
|
Type string `json:"type"` // 参数类型
|
||||||
Title string `json:"title"` // 参数标题
|
Title string `json:"title"` // 参数标题
|
||||||
Description string `json:"description"` // 参数描述
|
Description string `json:"description"` // 参数描述
|
||||||
|
Required bool `json:"required"` // 是否必传
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResultConfig 返回值配置
|
// ResultConfig 返回值配置
|
||||||
@ -46,3 +65,7 @@ type ResultConfig struct {
|
|||||||
Title string `json:"title"` // 返回值标题
|
Title string `json:"title"` // 返回值标题
|
||||||
Description string `json:"description"` // 返回值描述
|
Description string `json:"description"` // 返回值描述
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
UriParamRegexp = regexp.MustCompile("({.*?})") // uri路径中参数提取的正则表达式
|
||||||
|
)
|
||||||
|
@ -15,6 +15,8 @@ package define
|
|||||||
type SwaggerPathConfig struct {
|
type SwaggerPathConfig struct {
|
||||||
Description string `json:"description"` // 接口描述
|
Description string `json:"description"` // 接口描述
|
||||||
Consumes []string `json:"consumes"` // 请求方式, application/json等
|
Consumes []string `json:"consumes"` // 请求方式, application/json等
|
||||||
|
Produces []string `json:"produces"` // 请求方式, application/json等
|
||||||
|
OperationID string `json:"operationId"` // 操作ID
|
||||||
Tags []string `json:"tags"` // 接口标签
|
Tags []string `json:"tags"` // 接口标签
|
||||||
Summary string `json:"summary"` // 接口摘要
|
Summary string `json:"summary"` // 接口摘要
|
||||||
Parameters []*SwaggerPathConfigParameter `json:"parameters"` // 参数列表
|
Parameters []*SwaggerPathConfigParameter `json:"parameters"` // 参数列表
|
||||||
@ -28,12 +30,17 @@ type SwaggerPathConfig struct {
|
|||||||
// Date : 16:53 2024/4/19
|
// Date : 16:53 2024/4/19
|
||||||
type SwaggerPathConfigParameter struct {
|
type SwaggerPathConfigParameter struct {
|
||||||
Type string `json:"type,omitempty"` // 类型
|
Type string `json:"type,omitempty"` // 类型
|
||||||
|
Format string `json:"format"` // 格式化类型
|
||||||
Description string `json:"description"` // 描述
|
Description string `json:"description"` // 描述
|
||||||
Name string `json:"name"` // 参数名称
|
Name string `json:"name"` // 参数名称
|
||||||
In string `json:"in"` // 参数位置
|
In string `json:"in"` // 参数位置
|
||||||
Required bool `json:"required"` // 是否必传
|
Required bool `json:"required"` // 是否必传
|
||||||
EnumList []interface{} `json:"enum_list,omitempty"` // 枚举值列表
|
EnumList []any `json:"enum_list,omitempty"` // 枚举值列表
|
||||||
Schema map[string]string `json:"schema"` // 参数schema
|
Schema *SwaggerPathConfigParameterSchema `json:"schema"` // 参数schema
|
||||||
|
}
|
||||||
|
|
||||||
|
type SwaggerPathConfigParameterSchema struct {
|
||||||
|
Ref string `json:"$ref"` // 引用的数据结构定义
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwaggerPathConfigResponse ...
|
// SwaggerPathConfigResponse ...
|
||||||
@ -43,7 +50,16 @@ type SwaggerPathConfigParameter struct {
|
|||||||
// Date : 16:57 2024/4/19
|
// Date : 16:57 2024/4/19
|
||||||
type SwaggerPathConfigResponse struct {
|
type SwaggerPathConfigResponse struct {
|
||||||
Description string `json:"description"` // 返回值描述
|
Description string `json:"description"` // 返回值描述
|
||||||
Schema map[string]string `json:"schema"` // 返回值结构
|
Schema *SwaggerPathConfigResponseSchema `json:"schema"` // 返回值结构
|
||||||
|
Ref string `json:"$ref"` // 引用的数据
|
||||||
|
}
|
||||||
|
|
||||||
|
type SwaggerPathConfigResponseSchema struct {
|
||||||
|
Type string `json:"type"` // 数据类型
|
||||||
|
Items struct {
|
||||||
|
Ref string `json:"$ref"` // type = array 时, 引用的每一项数据结构
|
||||||
|
} `json:"items"`
|
||||||
|
Ref string `json:"$ref"` // 引用的数据结构
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwaggerDefinition ...
|
// SwaggerDefinition ...
|
||||||
@ -66,8 +82,17 @@ type SwaggerDefinition struct {
|
|||||||
type SwaggerDefinitionProperty struct {
|
type SwaggerDefinitionProperty struct {
|
||||||
Description string `json:"description"` // 描述
|
Description string `json:"description"` // 描述
|
||||||
Type string `json:"type"` // 类型
|
Type string `json:"type"` // 类型
|
||||||
Items map[string]string `json:"items,omitempty"` // 引用类型中的引用(数组)
|
Items *SwaggerDefinitionPropertyItem `json:"items,omitempty"` // 引用类型中的引用(数组)
|
||||||
AllOf []map[string]string `json:"allOf,omitempty"` // 引用类型中的引用(对象)
|
AllOf []map[string]string `json:"allOf,omitempty"` // 引用类型中的引用(对象)
|
||||||
|
XGoName string `json:"x-go-name"` // go字段名称
|
||||||
|
XGoPackage string `json:"x-go-package"` // go 包路径
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwaggerDefinitionPropertyItem 属性item兴义
|
||||||
|
type SwaggerDefinitionPropertyItem struct {
|
||||||
|
Type string `json:"type"` // 类型
|
||||||
|
Ref string `json:"$ref"` // 引用
|
||||||
|
Enum []any `json:"enum"` // 枚举值
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swagger 文档整体结构定义
|
// Swagger 文档整体结构定义
|
||||||
@ -83,6 +108,8 @@ type Swagger struct {
|
|||||||
Info Info `json:"info"` // 文档描述信息
|
Info Info `json:"info"` // 文档描述信息
|
||||||
Paths map[string]map[string]*SwaggerPathConfig `json:"paths"` // 接口列表 : 接口 => 请求方法 => 请求配置
|
Paths map[string]map[string]*SwaggerPathConfig `json:"paths"` // 接口列表 : 接口 => 请求方法 => 请求配置
|
||||||
Definitions map[string]*SwaggerDefinition `json:"definitions"` // 数据定义
|
Definitions map[string]*SwaggerDefinition `json:"definitions"` // 数据定义
|
||||||
|
Responses map[string]*SwaggerPathConfigResponse `json:"responses"` // 响应结构列表
|
||||||
|
SecurityDefinitions map[string]*SwaggerPathConfigParameter `json:"securityDefinitions"` // 安全选项
|
||||||
}
|
}
|
||||||
|
|
||||||
// SwaggerInput ...
|
// SwaggerInput ...
|
11
go.mod
11
go.mod
@ -3,19 +3,22 @@ module git.zhangdeman.cn/gateway/api-doc
|
|||||||
go 1.22.2
|
go 1.22.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240817091513-491f455a23c0
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241225030757-c00354fe4630
|
||||||
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd
|
||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95
|
||||||
|
github.com/tidwall/gjson v1.18.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 // indirect
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 // indirect
|
||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 // indirect
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect
|
||||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 // indirect
|
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
|
||||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
|
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mozillazg/go-pinyin v0.20.0 // indirect
|
github.com/mozillazg/go-pinyin v0.20.0 // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
37
go.sum
37
go.sum
@ -1,21 +1,17 @@
|
|||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240425091616-00e0a924efcd h1:RBFDiEMI97fuzpyb5HBN4lu3UXTAGYo6nlGhV2gWq5U=
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701 h1:G+lGQmjMOBWGspZfijZvenGUAKpjBBrkRXLg3+GZp0U=
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240425091616-00e0a924efcd/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240722080005-ca68a3ff8bc7 h1:8wJlcuJPhEHKdNIENvcxGiZwwOgjclvKwgKt/MU6WWI=
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241225030757-c00354fe4630 h1:KTp27pHr25X5khTi4B/OdFv/34UWkq6sgDfz5aBtj74=
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240722080005-ca68a3ff8bc7/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241225030757-c00354fe4630/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4 h1:mibnyzYbZullK0aTHVASHl3UeoVr8IgytQZsuyv+yEM=
|
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240817091513-491f455a23c0 h1:U12XDtyRrmsqb/wRvRZG9+SBKMCGFNADpiLogsp5POw=
|
|
||||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240817091513-491f455a23c0/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
|
||||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
|
||||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
|
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
|
||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0=
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
|
||||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw=
|
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
|
||||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 h1:GO3oZa5a2sqwAzGcLDJtQzmshSWRmoP7IDS8bwFqvC4=
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
|
||||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95 h1:3lO4ap9p7kEA+4yL5ojG9mAWsz5sY28Nu2tSzAZEehw=
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95 h1:3lO4ap9p7kEA+4yL5ojG9mAWsz5sY28Nu2tSzAZEehw=
|
||||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95/go.mod h1:Fo4XOiZPua4E4/Qzy3ZYS5zyd15bS/lsb3t6S6PQFGY=
|
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95/go.mod h1:Fo4XOiZPua4E4/Qzy3ZYS5zyd15bS/lsb3t6S6PQFGY=
|
||||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
|
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
|
||||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
|
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@ -30,8 +26,17 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
|
||||||
|
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||||
|
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
36
parser.go
36
parser.go
@ -7,17 +7,35 @@
|
|||||||
// Date : 2024-07-19 11:45
|
// Date : 2024-07-19 11:45
|
||||||
package api_doc
|
package api_doc
|
||||||
|
|
||||||
var (
|
import (
|
||||||
Parser = &parser{}
|
"git.zhangdeman.cn/gateway/api-doc/define"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type parser struct {
|
// Parse 解析swagger文档
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 16:54 2024/12/23
|
||||||
|
func Parse(docUrl string) (*define.DocParseResult, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
docContent []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
if docContent, err = serialize.File.ReadFromRemote(docUrl); nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
swaggerVersion := gjson.GetBytes(docContent, "swagger").String()
|
||||||
|
if "" == swaggerVersion || !strings.HasPrefix(swaggerVersion, "2.") {
|
||||||
|
// 未指定swagger版本或swagger版本3.x
|
||||||
|
return ParseOpenapi3(docContent)
|
||||||
|
}
|
||||||
|
return ParseSwagger2(docContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parser) Openapi3() {
|
func ParseOpenapi3(docContent []byte) (*define.DocParseResult, error) {
|
||||||
|
return nil, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (p *parser) swagger2() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.zhangdeman.cn/gateway/api-doc/define"
|
"git.zhangdeman.cn/gateway/api-doc/define"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"testing"
|
"testing"
|
||||||
@ -32,3 +33,9 @@ func Test_parser_Openapi3(t *testing.T) {
|
|||||||
fmt.Println("解析成功")
|
fmt.Println("解析成功")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseForSwagger(t *testing.T) {
|
||||||
|
docUrl := "https://git.zhangdeman.cn/swagger.v1.json"
|
||||||
|
res, _ := Parse(docUrl)
|
||||||
|
serialize.JSON.ConsoleOutput(res)
|
||||||
|
}
|
||||||
|
233
swagger.go
Normal file
233
swagger.go
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
// Package api_doc ...
|
||||||
|
//
|
||||||
|
// Description : api_doc ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2024-12-24 10:34
|
||||||
|
package api_doc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"git.zhangdeman.cn/gateway/api-doc/define"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/consts"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ParseSwagger2 解析swagger2.0版本文档
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 10:33 2024/12/24
|
||||||
|
func ParseSwagger2(docContent []byte) (*define.DocParseResult, error) {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
swaggerDoc define.Swagger
|
||||||
|
)
|
||||||
|
|
||||||
|
if err = serialize.JSON.UnmarshalWithNumber(docContent, &swaggerDoc); nil != err {
|
||||||
|
return nil, errors.New("parse swagger json fail : " + err.Error())
|
||||||
|
}
|
||||||
|
docResult := &define.DocParseResult{
|
||||||
|
Domain: swaggerDoc.Host,
|
||||||
|
Title: swaggerDoc.Info.Title,
|
||||||
|
Description: swaggerDoc.Info.Description,
|
||||||
|
UriList: make([]*define.UriBaseConfig, 0),
|
||||||
|
GlobalSecurityParamList: make([]*define.ParamConfig, 0),
|
||||||
|
}
|
||||||
|
if docResult.UriList, err = buildUriList(&swaggerDoc); nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
docResult.GlobalSecurityParamList = buildSwagger2GlobalSecurityParamList(&swaggerDoc)
|
||||||
|
return docResult, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildSwagger2GlobalSecurityParamList 构建全局安全类参数
|
||||||
|
func buildSwagger2GlobalSecurityParamList(swaggerDoc *define.Swagger) []*define.ParamConfig {
|
||||||
|
result := make([]*define.ParamConfig, 0)
|
||||||
|
for paramName, paramConfig := range swaggerDoc.SecurityDefinitions {
|
||||||
|
if len(paramConfig.In) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, &define.ParamConfig{
|
||||||
|
Location: GetParamLocation(paramConfig.In).String(),
|
||||||
|
Path: paramName,
|
||||||
|
Type: GetDataType(paramConfig.Type, "").String(),
|
||||||
|
Title: paramName,
|
||||||
|
Description: paramConfig.Description,
|
||||||
|
Required: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析uri列表
|
||||||
|
func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) {
|
||||||
|
uriList := make([]*define.UriBaseConfig, 0)
|
||||||
|
for itemUri, itemUriMethodConfig := range swaggerDoc.Paths {
|
||||||
|
for requestMethod, methodConfig := range itemUriMethodConfig {
|
||||||
|
initSwagger2UriMethodConfig(requestMethod, methodConfig)
|
||||||
|
uriResult := &define.UriBaseConfig{
|
||||||
|
Uri: swaggerDoc.BasePath + "/" + strings.TrimLeft(itemUri, "/"),
|
||||||
|
Method: strings.ToUpper(requestMethod),
|
||||||
|
ContentType: methodConfig.Consumes[0],
|
||||||
|
OutputContentType: methodConfig.Produces[0],
|
||||||
|
TagList: methodConfig.Tags,
|
||||||
|
Summary: methodConfig.Summary,
|
||||||
|
Description: methodConfig.Description,
|
||||||
|
ParamList: buildSwagger2ParamConfig(swaggerDoc, methodConfig.Parameters),
|
||||||
|
ResultList: buildSwagger2ResultConfig(swaggerDoc, methodConfig.Responses),
|
||||||
|
}
|
||||||
|
uriList = append(uriList, uriResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uriList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化配置请求方法 返回类型
|
||||||
|
func initSwagger2UriMethodConfig(requestMethod string, methodConfig *define.SwaggerPathConfig) {
|
||||||
|
if len(methodConfig.Consumes) == 0 {
|
||||||
|
// 未配置请求方法, 写请求 json , 读请求 form
|
||||||
|
if strings.ToUpper(requestMethod) == http.MethodPost ||
|
||||||
|
strings.ToUpper(requestMethod) == http.MethodPut ||
|
||||||
|
strings.ToUpper(requestMethod) == http.MethodPatch ||
|
||||||
|
strings.ToUpper(requestMethod) == http.MethodDelete {
|
||||||
|
methodConfig.Consumes = []string{
|
||||||
|
consts.MimeTypeJson,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
methodConfig.Consumes = []string{
|
||||||
|
consts.MimeTypeXWWWFormUrlencoded,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(methodConfig.Produces) == 0 {
|
||||||
|
// 未配置输出数据类型, 默认 json
|
||||||
|
methodConfig.Produces = []string{
|
||||||
|
consts.MimeTypeJson,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildSwagger2ParamConfig 构建请求参数配置
|
||||||
|
func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*define.SwaggerPathConfigParameter) []*define.ParamConfig {
|
||||||
|
res := make([]*define.ParamConfig, 0)
|
||||||
|
// 解析参数
|
||||||
|
for _, paramConfig := range paramConfigList {
|
||||||
|
if paramConfig.Name != "body" {
|
||||||
|
paramConfigBuildConfig := &define.ParamConfig{
|
||||||
|
Location: GetParamLocation(paramConfig.In).String(),
|
||||||
|
Path: paramConfig.Name,
|
||||||
|
Type: GetDataType(paramConfig.Type, paramConfig.Format).String(),
|
||||||
|
Title: paramConfig.Name,
|
||||||
|
Description: paramConfig.Description,
|
||||||
|
Required: paramConfig.Required,
|
||||||
|
}
|
||||||
|
res = append(res, paramConfigBuildConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil == paramConfig.Schema || len(paramConfig.Schema.Ref) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// 可以继续展开
|
||||||
|
requiredTable := make(map[string]bool)
|
||||||
|
for _, paramName := range swaggerDoc.Definitions[GetRealDefinitionsKey(paramConfig.Schema.Ref)].Required {
|
||||||
|
requiredTable[paramName] = true
|
||||||
|
}
|
||||||
|
for paramName, paramMoreConfig := range swaggerDoc.Definitions[GetRealDefinitionsKey(paramConfig.Schema.Ref)].Properties {
|
||||||
|
if paramConfig.Name != "body" {
|
||||||
|
paramName = paramConfig.Name + "." + paramName
|
||||||
|
}
|
||||||
|
paramConfigBuildConfig := &define.ParamConfig{
|
||||||
|
Location: GetParamLocation(paramConfig.In).String(),
|
||||||
|
Path: paramName,
|
||||||
|
Type: GetDataType(paramMoreConfig.Type, "").String(),
|
||||||
|
Title: paramName,
|
||||||
|
Description: paramMoreConfig.Description,
|
||||||
|
Required: requiredTable[paramName],
|
||||||
|
}
|
||||||
|
res = append(res, paramConfigBuildConfig)
|
||||||
|
if DataTypeIsArray(paramMoreConfig.Type) && nil != paramMoreConfig.Items && len(paramMoreConfig.Items.Ref) > 0 {
|
||||||
|
// 是数组,且每一项是对象, 继续展开
|
||||||
|
res = append(res, ExpandArrayParam(swaggerDoc, paramMoreConfig.Items.Ref, paramConfigBuildConfig.Path)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildSwagger2ResultConfig 构建响应结果配置
|
||||||
|
func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, resultConfig map[string]*define.SwaggerPathConfigResponse) []*define.ResultConfig {
|
||||||
|
res := make([]*define.ResultConfig, 0)
|
||||||
|
if nil == resultConfig || len(resultConfig) == 0 {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
successResponseConfig := GetSuccessResponseConfig(resultConfig)
|
||||||
|
if nil == successResponseConfig {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
definitionsKey := ""
|
||||||
|
if swaggerDoc.Responses == nil {
|
||||||
|
definitionsKey = successResponseConfig.Schema.Ref
|
||||||
|
} else {
|
||||||
|
responseKey := GetRealResponseKey(successResponseConfig.Ref)
|
||||||
|
if len(responseKey) == 0 {
|
||||||
|
// 204 场景下,可能没有响应body
|
||||||
|
res = append(res, &define.ResultConfig{
|
||||||
|
Location: consts.ResponseDataLocationBody.String(),
|
||||||
|
Path: consts.ResponseDataLocationBodyRoot.String(),
|
||||||
|
Type: consts.DataTypeAny.String(),
|
||||||
|
Title: "response body no content",
|
||||||
|
Description: "no content",
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
ref := swaggerDoc.Responses[responseKey].Ref
|
||||||
|
if len(ref) == 0 {
|
||||||
|
if nil != swaggerDoc.Responses[responseKey].Schema {
|
||||||
|
ref = swaggerDoc.Responses[responseKey].Schema.Ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
definitionsKey = GetRealDefinitionsKey(ref)
|
||||||
|
}
|
||||||
|
if len(definitionsKey) == 0 {
|
||||||
|
// 不是引用类型, 直接定义的具体类型
|
||||||
|
responseKey := GetRealResponseKey(successResponseConfig.Ref)
|
||||||
|
responseTypeDefine := swaggerDoc.Responses[responseKey]
|
||||||
|
responseType := ""
|
||||||
|
schemaType := ""
|
||||||
|
if nil == responseTypeDefine.Schema {
|
||||||
|
// 204 等场景下,可能没有响应body
|
||||||
|
responseType = consts.DataTypeAny.String()
|
||||||
|
} else {
|
||||||
|
schemaType = responseTypeDefine.Schema.Type
|
||||||
|
responseType = GetDataType(responseTypeDefine.Schema.Type, "").String()
|
||||||
|
}
|
||||||
|
resCfg := &define.ResultConfig{
|
||||||
|
Location: consts.ResponseDataLocationBody.String(),
|
||||||
|
Path: consts.ResponseDataLocationBodyRoot.String(),
|
||||||
|
Type: responseType,
|
||||||
|
Title: "response body",
|
||||||
|
Description: "response body",
|
||||||
|
}
|
||||||
|
res = append(res, resCfg)
|
||||||
|
if DataTypeIsArray(schemaType) && len(responseTypeDefine.Schema.Items.Ref) > 0 {
|
||||||
|
res = append(res, ExpandArrayResult(swaggerDoc, responseTypeDefine.Schema.Items.Ref, resCfg.Path)...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
responseTypeDefine := swaggerDoc.Definitions[definitionsKey]
|
||||||
|
for responseKey, responseKeyConfig := range responseTypeDefine.Properties {
|
||||||
|
res = append(res, &define.ResultConfig{
|
||||||
|
Location: consts.ResponseDataLocationBody.String(),
|
||||||
|
Path: responseKey,
|
||||||
|
Type: GetDataType(responseKeyConfig.Type, "").String(),
|
||||||
|
Title: responseKey,
|
||||||
|
Description: responseKey,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
@ -43,11 +43,13 @@ func Generate(docConfig *define.SwaggerInput) (*define.Swagger, error) {
|
|||||||
// Date : 10:54 2024/4/22
|
// Date : 10:54 2024/4/22
|
||||||
func formatDocConfig(docConfig *define.SwaggerInput) {
|
func formatDocConfig(docConfig *define.SwaggerInput) {
|
||||||
if len(docConfig.Schemes) == 0 {
|
if len(docConfig.Schemes) == 0 {
|
||||||
docConfig.Schemes = []string{consts.SchemeHTTP}
|
docConfig.Schemes = []string{
|
||||||
|
consts.SchemeHTTP.String(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
docConfig.Host = wrapper.String(docConfig.Host).ReplaceChar(map[string]string{
|
docConfig.Host = wrapper.String(docConfig.Host).ReplaceChar(map[string]string{
|
||||||
consts.SchemeHTTP + "://": "",
|
consts.SchemeHTTP.String() + "://": "",
|
||||||
consts.SchemeHTTPS + "://": "",
|
consts.SchemeHTTPS.String() + "://": "",
|
||||||
}).Value()
|
}).Value()
|
||||||
for _, itemPath := range docConfig.PathConfigList {
|
for _, itemPath := range docConfig.PathConfigList {
|
||||||
// 默认请求类型 application/json
|
// 默认请求类型 application/json
|
||||||
@ -79,7 +81,7 @@ func formatDocConfig(docConfig *define.SwaggerInput) {
|
|||||||
for _, itemResponse := range itemResponseConfig.List {
|
for _, itemResponse := range itemResponseConfig.List {
|
||||||
// 默认返回数据类型
|
// 默认返回数据类型
|
||||||
itemResponse.Type = strings.TrimSpace(itemResponse.Type)
|
itemResponse.Type = strings.TrimSpace(itemResponse.Type)
|
||||||
itemResponse.Type = wrapper.TernaryOperator.String(len(itemResponse.Type) == 0, consts.DataTypeString, wrapper.String(itemResponse.Type)).Value()
|
itemResponse.Type = wrapper.TernaryOperator.String(len(itemResponse.Type) == 0, wrapper.String(consts.DataTypeString), wrapper.String(itemResponse.Type)).Value()
|
||||||
// 填充默认描述
|
// 填充默认描述
|
||||||
itemResponse.Description = strings.TrimSpace(itemResponse.Description)
|
itemResponse.Description = strings.TrimSpace(itemResponse.Description)
|
||||||
itemResponse.Description = wrapper.TernaryOperator.String(len(itemResponse.Description) == 0, wrapper.String(itemResponse.Type+" : "+itemResponse.Field), wrapper.String(itemResponse.Description)).Value()
|
itemResponse.Description = wrapper.TernaryOperator.String(len(itemResponse.Description) == 0, wrapper.String(itemResponse.Type+" : "+itemResponse.Field), wrapper.String(itemResponse.Description)).Value()
|
||||||
@ -133,7 +135,7 @@ func generatePathParameterConfig(swaggerInfo *define.Swagger, pathConfig *define
|
|||||||
namePath := strings.Split(itemParamInput.Name, ".")
|
namePath := strings.Split(itemParamInput.Name, ".")
|
||||||
realParamName := namePath[0]
|
realParamName := namePath[0]
|
||||||
parentPath := ""
|
parentPath := ""
|
||||||
if strings.ToUpper(itemParamInput.In) == consts.RequestDataLocationBody && !strings.Contains(realParamName, ".") {
|
if strings.ToUpper(itemParamInput.In) == consts.RequestDataLocationBody.String() && !strings.Contains(realParamName, ".") {
|
||||||
realParamName = "jsonBody"
|
realParamName = "jsonBody"
|
||||||
parentPath = strings.ReplaceAll(pathConfig.Uri, ".", "-") + ".jsonBody"
|
parentPath = strings.ReplaceAll(pathConfig.Uri, ".", "-") + ".jsonBody"
|
||||||
}
|
}
|
||||||
@ -177,7 +179,7 @@ func generatePathResponseConfig(swaggerInfo *define.Swagger, pathConfig *define.
|
|||||||
Type: itemResponseInput.Type,
|
Type: itemResponseInput.Type,
|
||||||
Description: itemResponseInput.Description,
|
Description: itemResponseInput.Description,
|
||||||
Name: itemResponseInput.Field,
|
Name: itemResponseInput.Field,
|
||||||
In: consts.RequestDataLocationBody,
|
In: consts.RequestDataLocationBody.String(),
|
||||||
Required: false,
|
Required: false,
|
||||||
EnumList: nil,
|
EnumList: nil,
|
||||||
})
|
})
|
||||||
@ -186,8 +188,8 @@ func generatePathResponseConfig(swaggerInfo *define.Swagger, pathConfig *define.
|
|||||||
hasDealResponseTable[namePath[0]] = true
|
hasDealResponseTable[namePath[0]] = true
|
||||||
swaggerInfo.Paths[pathConfig.Uri][pathConfig.Method].Responses[itemResponseConfig.Code] = &define.SwaggerPathConfigResponse{
|
swaggerInfo.Paths[pathConfig.Uri][pathConfig.Method].Responses[itemResponseConfig.Code] = &define.SwaggerPathConfigResponse{
|
||||||
Description: "返回数据",
|
Description: "返回数据",
|
||||||
Schema: map[string]string{
|
Schema: &define.SwaggerPathConfigResponseSchema{
|
||||||
"$ref": getRefValue(outputDefine),
|
Ref: getRefValue(outputDefine),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,7 +300,7 @@ func generateParameterDefinitions(swaggerInfo *define.Swagger, uri string, paren
|
|||||||
//
|
//
|
||||||
// Date : 16:50 2024/4/25
|
// Date : 16:50 2024/4/25
|
||||||
func handleOneLevelSubPath(swaggerInfo *define.Swagger, uri string, parentPath string, subPath string, paramConfig *define.SwaggerParameterInput) {
|
func handleOneLevelSubPath(swaggerInfo *define.Swagger, uri string, parentPath string, subPath string, paramConfig *define.SwaggerParameterInput) {
|
||||||
if paramConfig.In != strings.ToLower(consts.RequestDataLocationBody) && !isGenerateOutput(parentPath) {
|
if paramConfig.In != strings.ToLower(consts.RequestDataLocationBody.String()) && !isGenerateOutput(parentPath) {
|
||||||
// 长度为1, 还不在 body, 无需生成结构体
|
// 长度为1, 还不在 body, 无需生成结构体
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -368,13 +370,13 @@ func setGlobalMapDefinition(swaggerInfo *define.Swagger, dataType string) {
|
|||||||
// Date : 15:46 2024/4/25
|
// Date : 15:46 2024/4/25
|
||||||
func isGlobalMapType(dataType string) bool {
|
func isGlobalMapType(dataType string) bool {
|
||||||
return wrapper.ArrayType([]string{
|
return wrapper.ArrayType([]string{
|
||||||
consts.DataTypeMapAnyAny,
|
consts.DataTypeMapAnyAny.String(),
|
||||||
consts.DataTypeMapStrUint,
|
consts.DataTypeMapStrUint.String(),
|
||||||
consts.DataTypeMapStrInt,
|
consts.DataTypeMapStrInt.String(),
|
||||||
consts.DataTypeMapStrSlice,
|
consts.DataTypeMapStrSlice.String(),
|
||||||
consts.DataTypeMapStrFloat,
|
consts.DataTypeMapStrFloat.String(),
|
||||||
consts.DataTypeMapStrBool,
|
consts.DataTypeMapStrBool.String(),
|
||||||
consts.DataTypeMapStrAny,
|
consts.DataTypeMapStrAny.String(),
|
||||||
}).Has(dataType) >= 0
|
}).Has(dataType) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +397,7 @@ func initAnyDefinition(swaggerInfo *define.Swagger, definitionName string) {
|
|||||||
}
|
}
|
||||||
swaggerInfo.Definitions[definitionName] = &define.SwaggerDefinition{
|
swaggerInfo.Definitions[definitionName] = &define.SwaggerDefinition{
|
||||||
Type: consts.SwaggerDataTypeObject,
|
Type: consts.SwaggerDataTypeObject,
|
||||||
Format: consts.DataTypeMapStrAny,
|
Format: consts.DataTypeMapStrAny.String(),
|
||||||
Required: make([]string, 0),
|
Required: make([]string, 0),
|
||||||
Properties: make(map[string]*define.SwaggerDefinitionProperty),
|
Properties: make(map[string]*define.SwaggerDefinitionProperty),
|
||||||
}
|
}
|
||||||
|
@ -25,12 +25,12 @@ func TestGenerate(t *testing.T) {
|
|||||||
Info: define.Info{
|
Info: define.Info{
|
||||||
Description: "测试",
|
Description: "测试",
|
||||||
Title: "测试",
|
Title: "测试",
|
||||||
Contact: define.Contact{
|
Contact: &define.Contact{
|
||||||
Name: "白茶",
|
Name: "白茶",
|
||||||
Url: "http://www.baidu.com",
|
Url: "http://www.baidu.com",
|
||||||
Email: "go@email.com",
|
Email: "go@email.com",
|
||||||
},
|
},
|
||||||
License: define.License{
|
License: &define.License{
|
||||||
Name: consts.LicenseApache20,
|
Name: consts.LicenseApache20,
|
||||||
Url: consts.LicenseUrlTable[consts.LicenseApache20],
|
Url: consts.LicenseUrlTable[consts.LicenseApache20],
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user