From 8f4c6c3b6ba4e8c4d7fd017f7751be71ce543ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Mon, 23 Dec 2024 16:07:10 +0800 Subject: [PATCH 01/14] update define --- define/{types.go => swagger.go} | 0 go.mod | 2 +- go.sum | 2 ++ swagger/run_test.go | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) rename define/{types.go => swagger.go} (100%) diff --git a/define/types.go b/define/swagger.go similarity index 100% rename from define/types.go rename to define/swagger.go diff --git a/go.mod b/go.mod index 0cbd41e..dddae58 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.zhangdeman.cn/gateway/api-doc go 1.22.2 require ( - git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240817091513-491f455a23c0 + git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701 git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95 ) diff --git a/go.sum b/go.sum index 5e1b3f0..1c661e4 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240726024939-e424db29c5c4 h1:mibnyz 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/consts v0.0.0-20241125100843-b1b286c7a701 h1:G+lGQmjMOBWGspZfijZvenGUAKpjBBrkRXLg3+GZp0U= +git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701/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/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0= diff --git a/swagger/run_test.go b/swagger/run_test.go index a9b3c4e..2cef0bb 100644 --- a/swagger/run_test.go +++ b/swagger/run_test.go @@ -25,12 +25,12 @@ func TestGenerate(t *testing.T) { Info: define.Info{ Description: "测试", Title: "测试", - Contact: define.Contact{ + Contact: &define.Contact{ Name: "白茶", Url: "http://www.baidu.com", Email: "go@email.com", }, - License: define.License{ + License: &define.License{ Name: consts.LicenseApache20, Url: consts.LicenseUrlTable[consts.LicenseApache20], }, -- 2.36.6 From 15beb6bae028b0ada6675f27f2c1f0be44267b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Mon, 23 Dec 2024 16:56:39 +0800 Subject: [PATCH 02/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0swagger=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=85=A5=E5=8F=A3=E6=96=B9=E6=B3=95+=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=88=86=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 6 +++--- go.sum | 6 ++++++ parser.go | 35 ++++++++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index dddae58..15f34ce 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,9 @@ require ( require ( 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-20231227095334-7eb5cdbf9253 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect + git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd // indirect + git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect github.com/go-ini/ini v1.67.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect diff --git a/go.sum b/go.sum index 1c661e4..7f16190 100644 --- a/go.sum +++ b/go.sum @@ -12,12 +12,18 @@ git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOs 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-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw= +git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI= +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-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI= +git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI= +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/go.mod h1:Fo4XOiZPua4E4/Qzy3ZYS5zyd15bS/lsb3t6S6PQFGY= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +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/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/parser.go b/parser.go index 409886a..9dc1d3c 100644 --- a/parser.go +++ b/parser.go @@ -7,17 +7,38 @@ // Date : 2024-07-19 11:45 package api_doc -var ( - Parser = &parser{} +import ( + "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) (any, 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, "3.") { + // 未指定swagger版本或swagger版本3.x + return ParseOpenapi3(docContent) + } + return ParseSwagger2(docContent) } -func (p *parser) Openapi3() { - +func ParseOpenapi3(docContent []byte) (any, error) { + return nil, nil } -func (p *parser) swagger2() { - +func ParseSwagger2(docContent []byte) (any, error) { + return nil, nil } -- 2.36.6 From fb9e22ac6638d75d07c71af03809ee4b9e80a8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Mon, 23 Dec 2024 17:56:01 +0800 Subject: [PATCH 03/14] fix err --- swagger/run.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/swagger/run.go b/swagger/run.go index 6f59a91..c82b620 100644 --- a/swagger/run.go +++ b/swagger/run.go @@ -43,11 +43,13 @@ func Generate(docConfig *define.SwaggerInput) (*define.Swagger, error) { // Date : 10:54 2024/4/22 func formatDocConfig(docConfig *define.SwaggerInput) { 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{ - consts.SchemeHTTP + "://": "", - consts.SchemeHTTPS + "://": "", + consts.SchemeHTTP.String() + "://": "", + consts.SchemeHTTPS.String() + "://": "", }).Value() for _, itemPath := range docConfig.PathConfigList { // 默认请求类型 application/json @@ -79,7 +81,7 @@ func formatDocConfig(docConfig *define.SwaggerInput) { for _, itemResponse := range itemResponseConfig.List { // 默认返回数据类型 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 = 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, ".") realParamName := namePath[0] parentPath := "" - if strings.ToUpper(itemParamInput.In) == consts.RequestDataLocationBody && !strings.Contains(realParamName, ".") { + if strings.ToUpper(itemParamInput.In) == consts.RequestDataLocationBody.String() && !strings.Contains(realParamName, ".") { realParamName = "jsonBody" parentPath = strings.ReplaceAll(pathConfig.Uri, ".", "-") + ".jsonBody" } @@ -177,7 +179,7 @@ func generatePathResponseConfig(swaggerInfo *define.Swagger, pathConfig *define. Type: itemResponseInput.Type, Description: itemResponseInput.Description, Name: itemResponseInput.Field, - In: consts.RequestDataLocationBody, + In: consts.RequestDataLocationBody.String(), Required: false, EnumList: nil, }) @@ -186,8 +188,8 @@ func generatePathResponseConfig(swaggerInfo *define.Swagger, pathConfig *define. hasDealResponseTable[namePath[0]] = true swaggerInfo.Paths[pathConfig.Uri][pathConfig.Method].Responses[itemResponseConfig.Code] = &define.SwaggerPathConfigResponse{ Description: "返回数据", - Schema: map[string]string{ - "$ref": getRefValue(outputDefine), + Schema: &define.SwaggerPathConfigResponseSchema{ + Ref: getRefValue(outputDefine), }, } } @@ -298,7 +300,7 @@ func generateParameterDefinitions(swaggerInfo *define.Swagger, uri string, paren // // Date : 16:50 2024/4/25 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, 无需生成结构体 return } @@ -368,13 +370,13 @@ func setGlobalMapDefinition(swaggerInfo *define.Swagger, dataType string) { // Date : 15:46 2024/4/25 func isGlobalMapType(dataType string) bool { return wrapper.ArrayType([]string{ - consts.DataTypeMapAnyAny, - consts.DataTypeMapStrUint, - consts.DataTypeMapStrInt, - consts.DataTypeMapStrSlice, - consts.DataTypeMapStrFloat, - consts.DataTypeMapStrBool, - consts.DataTypeMapStrAny, + consts.DataTypeMapAnyAny.String(), + consts.DataTypeMapStrUint.String(), + consts.DataTypeMapStrInt.String(), + consts.DataTypeMapStrSlice.String(), + consts.DataTypeMapStrFloat.String(), + consts.DataTypeMapStrBool.String(), + consts.DataTypeMapStrAny.String(), }).Has(dataType) >= 0 } @@ -395,7 +397,7 @@ func initAnyDefinition(swaggerInfo *define.Swagger, definitionName string) { } swaggerInfo.Definitions[definitionName] = &define.SwaggerDefinition{ Type: consts.SwaggerDataTypeObject, - Format: consts.DataTypeMapStrAny, + Format: consts.DataTypeMapStrAny.String(), Required: make([]string, 0), Properties: make(map[string]*define.SwaggerDefinitionProperty), } -- 2.36.6 From d069ead94ea4a9d6de9a2d18e844526546ab9aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 10:34:28 +0800 Subject: [PATCH 04/14] =?UTF-8?q?=E8=A7=84=E5=88=92swagger=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- define/generate.go | 25 +++++++++++++++++++------ define/swagger.go | 12 ++++++++++-- go.mod | 5 ++++- go.sum | 25 +++++++++---------------- parser.go | 23 +++++++++++++++++++---- parser_test.go | 5 +++++ 6 files changed, 66 insertions(+), 29 deletions(-) diff --git a/define/generate.go b/define/generate.go index aa97da3..a8a4770 100644 --- a/define/generate.go +++ b/define/generate.go @@ -7,18 +7,31 @@ // Date : 2024-08-14 15:20 package define +// DocParseResult 文档解析结果 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 10:30 2024/12/24 +type DocParseResult struct { + Domain string `json:"domain"` // 域名 + Description string `json:"description"` // 描述 + UriList []string `json:"uri_list"` // 接口列表 +} + // UriBaseConfig 添加接口时的基础配置 // // Author : go_developer@163.com<白茶清欢> // // Date : 15:21 2024/8/14 type UriBaseConfig struct { - Uri string `json:"uri"` // 接口路由 - Method string `json:"method"` // 接口请求方法 - ContentType string `json:"content_type"` // 接口请求类型 - TagList []string `json:"tag_list"` // 接口标签列表 - Summary string `json:"summary"` // 接口摘要描述 - Description string `json:"description"` // 接口详细描述 + Uri string `json:"uri"` // 接口路由 + Method string `json:"method"` // 接口请求方法 + ContentType string `json:"content_type"` // 接口请求类型 + TagList []string `json:"tag_list"` // 接口标签列表 + Summary string `json:"summary"` // 接口摘要描述 + Description string `json:"description"` // 接口详细描述 + ParamList []*ParamConfig `json:"param_list"` // 参数列表 + ResultList []*ResultConfig `json:"result_list"` // 返回值列表 } // ParamConfig 参数配置 diff --git a/define/swagger.go b/define/swagger.go index 86c48eb..1ba01ea 100644 --- a/define/swagger.go +++ b/define/swagger.go @@ -42,8 +42,16 @@ type SwaggerPathConfigParameter struct { // // Date : 16:57 2024/4/19 type SwaggerPathConfigResponse struct { - Description string `json:"description"` // 返回值描述 - Schema map[string]string `json:"schema"` // 返回值结构 + Description string `json:"description"` // 返回值描述 + Schema *SwaggerPathConfigResponseSchema `json:"schema"` // 返回值结构 +} + +type SwaggerPathConfigResponseSchema struct { + Type string `json:"type"` // 数据类型 + Items struct { + Ref string `json:"$ref"` // type = array 时, 引用的每一项数据结构 + } `json:"items"` + Ref string `json:"$ref"` // 引用的数据结构 } // SwaggerDefinition ... diff --git a/go.mod b/go.mod index 15f34ce..f5f5fea 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,13 @@ go 1.22.2 require ( git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701 + git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240422034417-8c922be06d95 + github.com/tidwall/gjson v1.16.0 ) require ( git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 // indirect - git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd // indirect git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e // indirect github.com/BurntSushi/toml v1.4.0 // indirect github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect @@ -17,5 +18,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mozillazg/go-pinyin v0.20.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 ) diff --git a/go.sum b/go.sum index 7f16190..38690da 100644 --- a/go.sum +++ b/go.sum @@ -1,27 +1,13 @@ -git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240425091616-00e0a924efcd h1:RBFDiEMI97fuzpyb5HBN4lu3UXTAGYo6nlGhV2gWq5U= -git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240425091616-00e0a924efcd/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-20240722080005-ca68a3ff8bc7/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/consts v0.0.0-20241125100843-b1b286c7a701 h1:G+lGQmjMOBWGspZfijZvenGUAKpjBBrkRXLg3+GZp0U= git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701/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/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-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI= 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-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI= git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI= 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/go.mod h1:Fo4XOiZPua4E4/Qzy3ZYS5zyd15bS/lsb3t6S6PQFGY= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= 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= @@ -38,8 +24,15 @@ 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/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= 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.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +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/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/parser.go b/parser.go index 9dc1d3c..fbfa0a6 100644 --- a/parser.go +++ b/parser.go @@ -8,6 +8,8 @@ package api_doc import ( + "errors" + "git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/zhangdeman/serialize" "github.com/tidwall/gjson" "strings" @@ -18,7 +20,7 @@ import ( // Author : go_developer@163.com<白茶清欢> // // Date : 16:54 2024/12/23 -func Parse(docUrl string) (any, error) { +func Parse(docUrl string) (*define.DocParseResult, error) { var ( err error docContent []byte @@ -28,17 +30,30 @@ func Parse(docUrl string) (any, error) { return nil, err } swaggerVersion := gjson.GetBytes(docContent, "swagger").String() - if "" == swaggerVersion || strings.HasPrefix(swaggerVersion, "3.") { + if "" == swaggerVersion || !strings.HasPrefix(swaggerVersion, "2.") { // 未指定swagger版本或swagger版本3.x return ParseOpenapi3(docContent) } return ParseSwagger2(docContent) } -func ParseOpenapi3(docContent []byte) (any, error) { +// 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()) + } return nil, nil } -func ParseSwagger2(docContent []byte) (any, error) { +func ParseOpenapi3(docContent []byte) (*define.DocParseResult, error) { return nil, nil } diff --git a/parser_test.go b/parser_test.go index 25b76b7..149598a 100644 --- a/parser_test.go +++ b/parser_test.go @@ -32,3 +32,8 @@ func Test_parser_Openapi3(t *testing.T) { fmt.Println("解析成功") } } + +func TestParseForSwagger(t *testing.T) { + docUrl := "https://git.zhangdeman.cn/swagger.v1.json" + _, _ = Parse(docUrl) +} -- 2.36.6 From 9df646324faae478e851ead5e180bd62b16e81e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 11:18:15 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0uri=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 39 +++++++++++++++++++++++++++++++++++ define/generate.go | 13 +++++++++--- parser.go | 18 ---------------- swagger.go | 51 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 21 deletions(-) create mode 100644 common.go create mode 100644 swagger.go diff --git a/common.go b/common.go new file mode 100644 index 0000000..edcde63 --- /dev/null +++ b/common.go @@ -0,0 +1,39 @@ +// Package api_doc ... +// +// Description : api_doc ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-12-24 10:52 +package api_doc + +import ( + "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, + }) + } + return result +} diff --git a/define/generate.go b/define/generate.go index a8a4770..ef576b1 100644 --- a/define/generate.go +++ b/define/generate.go @@ -7,15 +7,18 @@ // Date : 2024-08-14 15:20 package define +import "regexp" + // DocParseResult 文档解析结果 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:30 2024/12/24 type DocParseResult struct { - Domain string `json:"domain"` // 域名 - Description string `json:"description"` // 描述 - UriList []string `json:"uri_list"` // 接口列表 + Domain string `json:"domain"` // 域名 + Title string `json:"title"` // 标题 + Description string `json:"description"` // 描述 + UriList []*UriBaseConfig `json:"uri_list"` // 接口列表 } // UriBaseConfig 添加接口时的基础配置 @@ -59,3 +62,7 @@ type ResultConfig struct { Title string `json:"title"` // 返回值标题 Description string `json:"description"` // 返回值描述 } + +var ( + UriParamRegexp = regexp.MustCompile("({.*?})") // uri路径中参数提取的正则表达式 +) diff --git a/parser.go b/parser.go index fbfa0a6..327fe9f 100644 --- a/parser.go +++ b/parser.go @@ -8,7 +8,6 @@ package api_doc import ( - "errors" "git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/zhangdeman/serialize" "github.com/tidwall/gjson" @@ -37,23 +36,6 @@ func Parse(docUrl string) (*define.DocParseResult, error) { return ParseSwagger2(docContent) } -// 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()) - } - return nil, nil -} - func ParseOpenapi3(docContent []byte) (*define.DocParseResult, error) { return nil, nil } diff --git a/swagger.go b/swagger.go new file mode 100644 index 0000000..c5ecfaf --- /dev/null +++ b/swagger.go @@ -0,0 +1,51 @@ +// Package api_doc ... +// +// Description : api_doc ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-12-24 10:34 +package api_doc + +import ( + "errors" + "fmt" + "git.zhangdeman.cn/gateway/api-doc/define" + "git.zhangdeman.cn/zhangdeman/serialize" +) + +// 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), + } + if docResult.UriList, err = buildUriList(&swaggerDoc); nil != err { + return nil, err + } + return docResult, nil +} + +// 解析uri列表 +func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) { + uriList := make([]*define.UriBaseConfig, 0) + for itemUri, itemUriMethodConfig := range swaggerDoc.Paths { + GetUriPathParamList(itemUri) + fmt.Println(itemUriMethodConfig) + } + return uriList, nil +} -- 2.36.6 From ff2fa198eea6392225a54668f41b35096db993ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 12:11:17 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BD=93=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++ define/generate.go | 18 +++++++++-------- define/swagger.go | 4 ++++ swagger.go | 42 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 101 insertions(+), 11 deletions(-) diff --git a/common.go b/common.go index edcde63..4580533 100644 --- a/common.go +++ b/common.go @@ -33,7 +33,55 @@ func GetUriPathParamList(uriPath string) []*define.ParamConfig { Type: consts.DataTypeString.String(), Title: param, Description: param, + IsRequired: true, }) } return result } + +// GetParamType 将文档配置的数据类型转换为归一化处理后的数据类型 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:52 2024/12/24 +func GetParamType(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": + return consts.DataTypeString + 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 + } +} diff --git a/define/generate.go b/define/generate.go index ef576b1..08584ce 100644 --- a/define/generate.go +++ b/define/generate.go @@ -27,14 +27,15 @@ type DocParseResult struct { // // Date : 15:21 2024/8/14 type UriBaseConfig struct { - Uri string `json:"uri"` // 接口路由 - Method string `json:"method"` // 接口请求方法 - ContentType string `json:"content_type"` // 接口请求类型 - TagList []string `json:"tag_list"` // 接口标签列表 - Summary string `json:"summary"` // 接口摘要描述 - Description string `json:"description"` // 接口详细描述 - ParamList []*ParamConfig `json:"param_list"` // 参数列表 - ResultList []*ResultConfig `json:"result_list"` // 返回值列表 + Uri string `json:"uri"` // 接口路由 + Method string `json:"method"` // 接口请求方法 + ContentType string `json:"content_type"` // 接口请求类型 + OutputContentType string `json:"output_content_type"` // 输出数据类型 + TagList []string `json:"tag_list"` // 接口标签列表 + Summary string `json:"summary"` // 接口摘要描述 + Description string `json:"description"` // 接口详细描述 + ParamList []*ParamConfig `json:"param_list"` // 参数列表 + ResultList []*ResultConfig `json:"result_list"` // 返回值列表 } // ParamConfig 参数配置 @@ -48,6 +49,7 @@ type ParamConfig struct { Type string `json:"type"` // 参数类型 Title string `json:"title"` // 参数标题 Description string `json:"description"` // 参数描述 + IsRequired bool `json:"is_required"` // 是否必传 } // ResultConfig 返回值配置 diff --git a/define/swagger.go b/define/swagger.go index 1ba01ea..f6ee591 100644 --- a/define/swagger.go +++ b/define/swagger.go @@ -15,6 +15,8 @@ package define type SwaggerPathConfig struct { Description string `json:"description"` // 接口描述 Consumes []string `json:"consumes"` // 请求方式, application/json等 + Produces []string `json:"produces"` // 请求方式, application/json等 + OperationID string `json:"operationId"` // 操作ID Tags []string `json:"tags"` // 接口标签 Summary string `json:"summary"` // 接口摘要 Parameters []*SwaggerPathConfigParameter `json:"parameters"` // 参数列表 @@ -76,6 +78,8 @@ type SwaggerDefinitionProperty struct { Type string `json:"type"` // 类型 Items map[string]string `json:"items,omitempty"` // 引用类型中的引用(数组) AllOf []map[string]string `json:"allOf,omitempty"` // 引用类型中的引用(对象) + XGoName string `json:"x-go-name"` // go字段名称 + XGoPackage string `json:"x-go-package"` // go 包路径 } // Swagger 文档整体结构定义 diff --git a/swagger.go b/swagger.go index c5ecfaf..11602ff 100644 --- a/swagger.go +++ b/swagger.go @@ -9,9 +9,11 @@ package api_doc import ( "errors" - "fmt" "git.zhangdeman.cn/gateway/api-doc/define" + "git.zhangdeman.cn/zhangdeman/consts" "git.zhangdeman.cn/zhangdeman/serialize" + "net/http" + "strings" ) // ParseSwagger2 解析swagger2.0版本文档 @@ -44,8 +46,42 @@ func ParseSwagger2(docContent []byte) (*define.DocParseResult, error) { func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) { uriList := make([]*define.UriBaseConfig, 0) for itemUri, itemUriMethodConfig := range swaggerDoc.Paths { - GetUriPathParamList(itemUri) - fmt.Println(itemUriMethodConfig) + for requestMethod, methodConfig := range itemUriMethodConfig { + 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, + } + } + 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: make([]*define.ParamConfig, 0), + ResultList: nil, + } + // 解析query/body/header参数 + uriList = append(uriList, uriResult) + } } return uriList, nil } -- 2.36.6 From dd46f5ad807cc28c30febbd6688aad82022ae269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 12:33:50 +0800 Subject: [PATCH 07/14] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 4 +-- define/generate.go | 2 +- define/swagger.go | 19 +++++++----- swagger.go | 72 +++++++++++++++++++++++++++++++--------------- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/common.go b/common.go index 4580533..497c02d 100644 --- a/common.go +++ b/common.go @@ -33,7 +33,7 @@ func GetUriPathParamList(uriPath string) []*define.ParamConfig { Type: consts.DataTypeString.String(), Title: param, Description: param, - IsRequired: true, + Required: true, }) } return result @@ -59,7 +59,7 @@ func GetParamType(docParamType string, formatType string) consts.DataType { case "string": return consts.DataTypeString default: - return consts.DataTypeAny + return consts.DataTypeMapStrAny } } diff --git a/define/generate.go b/define/generate.go index 08584ce..7f66fcf 100644 --- a/define/generate.go +++ b/define/generate.go @@ -49,7 +49,7 @@ type ParamConfig struct { Type string `json:"type"` // 参数类型 Title string `json:"title"` // 参数标题 Description string `json:"description"` // 参数描述 - IsRequired bool `json:"is_required"` // 是否必传 + Required bool `json:"required"` // 是否必传 } // ResultConfig 返回值配置 diff --git a/define/swagger.go b/define/swagger.go index f6ee591..b7bdcea 100644 --- a/define/swagger.go +++ b/define/swagger.go @@ -29,13 +29,18 @@ type SwaggerPathConfig struct { // // Date : 16:53 2024/4/19 type SwaggerPathConfigParameter struct { - Type string `json:"type,omitempty"` // 类型 - Description string `json:"description"` // 描述 - Name string `json:"name"` // 参数名称 - In string `json:"in"` // 参数位置 - Required bool `json:"required"` // 是否必传 - EnumList []interface{} `json:"enum_list,omitempty"` // 枚举值列表 - Schema map[string]string `json:"schema"` // 参数schema + Type string `json:"type,omitempty"` // 类型 + Format string `json:"format"` // 格式化类型 + Description string `json:"description"` // 描述 + Name string `json:"name"` // 参数名称 + In string `json:"in"` // 参数位置 + Required bool `json:"required"` // 是否必传 + EnumList []any `json:"enum_list,omitempty"` // 枚举值列表 + Schema *SwaggerPathConfigParameterScheme `json:"schema"` // 参数schema +} + +type SwaggerPathConfigParameterScheme struct { + Ref string `json:"$ref"` // 引用的数据结构定义 } // SwaggerPathConfigResponse ... diff --git a/swagger.go b/swagger.go index 11602ff..325b499 100644 --- a/swagger.go +++ b/swagger.go @@ -47,27 +47,7 @@ func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) { uriList := make([]*define.UriBaseConfig, 0) for itemUri, itemUriMethodConfig := range swaggerDoc.Paths { for requestMethod, methodConfig := range itemUriMethodConfig { - 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, - } - } + initSwagger2UriMethodConfig(requestMethod, methodConfig) uriResult := &define.UriBaseConfig{ Uri: swaggerDoc.BasePath + "/" + strings.TrimLeft(itemUri, "/"), Method: strings.ToUpper(requestMethod), @@ -76,12 +56,58 @@ func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) { TagList: methodConfig.Tags, Summary: methodConfig.Summary, Description: methodConfig.Description, - ParamList: make([]*define.ParamConfig, 0), + ParamList: buildSwagger2ParamConfig(swaggerDoc, methodConfig.Parameters), ResultList: nil, } - // 解析query/body/header参数 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 { + paramConfigBuildConfig := &define.ParamConfig{ + Location: GetParamLocation(paramConfig.In).String(), + Path: paramConfig.Name, + Type: GetParamType(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 { + // TODO : 可以继续展开 + } + } + + return res +} -- 2.36.6 From e044ff3e59eeba427fc619118317af3c84d185a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 14:34:19 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=9C=9F=E5=AE=9Edefinitions=20key=E6=96=B9=E6=B3=95,=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=8F=82=E6=95=B0=E9=85=8D=E7=BD=AE=E6=9E=84?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 5 +++++ swagger.go | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/common.go b/common.go index 497c02d..ddd2043 100644 --- a/common.go +++ b/common.go @@ -85,3 +85,8 @@ func GetParamLocation(docParamLocation string) consts.RequestDataLocation { return consts.RequestDataLocationQuery } } + +// GetRealDefinitionsKey 统统schema下的 $ref 获取真实的 definitions key +func GetRealDefinitionsKey(ref string) string { + return strings.TrimPrefix(ref, "#/definitions/") +} diff --git a/swagger.go b/swagger.go index 325b499..897baa9 100644 --- a/swagger.go +++ b/swagger.go @@ -95,17 +95,39 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def res := make([]*define.ParamConfig, 0) // 解析参数 for _, paramConfig := range paramConfigList { - paramConfigBuildConfig := &define.ParamConfig{ - Location: GetParamLocation(paramConfig.In).String(), - Path: paramConfig.Name, - Type: GetParamType(paramConfig.Type, paramConfig.Format).String(), - Title: paramConfig.Name, - Description: paramConfig.Description, - Required: paramConfig.Required, + if paramConfig.Name != "body" { + paramConfigBuildConfig := &define.ParamConfig{ + Location: GetParamLocation(paramConfig.In).String(), + Path: paramConfig.Name, + Type: GetParamType(paramConfig.Type, paramConfig.Format).String(), + Title: paramConfig.Name, + Description: paramConfig.Description, + Required: paramConfig.Required, + } + res = append(res, paramConfigBuildConfig) } - res = append(res, paramConfigBuildConfig) - if nil != paramConfig.Schema && len(paramConfig.Schema.Ref) > 0 { - // TODO : 可以继续展开 + + 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: GetParamType(paramMoreConfig.Type, "").String(), + Title: paramMoreConfig.Description, + Description: paramMoreConfig.Description, + Required: requiredTable[paramName], + } + res = append(res, paramConfigBuildConfig) } } -- 2.36.6 From 4bae1254456096961045a43118ff532d3eb78d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 16:59:37 +0800 Subject: [PATCH 09/14] update common --- common.go | 10 ++++++++++ define/swagger.go | 23 +++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/common.go b/common.go index ddd2043..a7c03b2 100644 --- a/common.go +++ b/common.go @@ -58,6 +58,16 @@ func GetParamType(docParamType string, formatType string) consts.DataType { return consts.DataTypeUint case "string": return consts.DataTypeString + case "object": + return consts.DataTypeMapStrAny + case "array": + if formatType == "integer" { + return consts.DataTypeSliceInt + } else if formatType == "string" { + return consts.DataTypeSliceString + } else { + return consts.DataTypeSliceAny + } default: return consts.DataTypeMapStrAny } diff --git a/define/swagger.go b/define/swagger.go index b7bdcea..8c1d4b2 100644 --- a/define/swagger.go +++ b/define/swagger.go @@ -36,10 +36,10 @@ type SwaggerPathConfigParameter struct { In string `json:"in"` // 参数位置 Required bool `json:"required"` // 是否必传 EnumList []any `json:"enum_list,omitempty"` // 枚举值列表 - Schema *SwaggerPathConfigParameterScheme `json:"schema"` // 参数schema + Schema *SwaggerPathConfigParameterSchema `json:"schema"` // 参数schema } -type SwaggerPathConfigParameterScheme struct { +type SwaggerPathConfigParameterSchema struct { Ref string `json:"$ref"` // 引用的数据结构定义 } @@ -79,12 +79,19 @@ type SwaggerDefinition struct { // // Date : 17:25 2024/4/19 type SwaggerDefinitionProperty struct { - Description string `json:"description"` // 描述 - Type string `json:"type"` // 类型 - Items map[string]string `json:"items,omitempty"` // 引用类型中的引用(数组) - AllOf []map[string]string `json:"allOf,omitempty"` // 引用类型中的引用(对象) - XGoName string `json:"x-go-name"` // go字段名称 - XGoPackage string `json:"x-go-package"` // go 包路径 + Description string `json:"description"` // 描述 + Type string `json:"type"` // 类型 + Items *SwaggerDefinitionPropertyItem `json:"items,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 文档整体结构定义 -- 2.36.6 From 3722798c422fd5ab29c0c570aa85e587a18bd05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Tue, 24 Dec 2024 17:49:20 +0800 Subject: [PATCH 10/14] fix --- common.go | 7 ++++++- define/swagger.go | 2 ++ swagger.go | 43 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/common.go b/common.go index a7c03b2..de1731d 100644 --- a/common.go +++ b/common.go @@ -96,7 +96,12 @@ func GetParamLocation(docParamLocation string) consts.RequestDataLocation { } } -// GetRealDefinitionsKey 统统schema下的 $ref 获取真实的 definitions key +// 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/") +} diff --git a/define/swagger.go b/define/swagger.go index 8c1d4b2..1fbfab2 100644 --- a/define/swagger.go +++ b/define/swagger.go @@ -51,6 +51,7 @@ type SwaggerPathConfigParameterSchema struct { type SwaggerPathConfigResponse struct { Description string `json:"description"` // 返回值描述 Schema *SwaggerPathConfigResponseSchema `json:"schema"` // 返回值结构 + Ref string `json:"$ref"` // 引用的数据 } type SwaggerPathConfigResponseSchema struct { @@ -107,6 +108,7 @@ type Swagger struct { Info Info `json:"info"` // 文档描述信息 Paths map[string]map[string]*SwaggerPathConfig `json:"paths"` // 接口列表 : 接口 => 请求方法 => 请求配置 Definitions map[string]*SwaggerDefinition `json:"definitions"` // 数据定义 + Responses map[string]*SwaggerPathConfigResponse `json:"responses"` // 响应结构列表 } // SwaggerInput ... diff --git a/swagger.go b/swagger.go index 897baa9..e9fdb8a 100644 --- a/swagger.go +++ b/swagger.go @@ -57,7 +57,7 @@ func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) { Summary: methodConfig.Summary, Description: methodConfig.Description, ParamList: buildSwagger2ParamConfig(swaggerDoc, methodConfig.Parameters), - ResultList: nil, + ResultList: buildSwagger2ResultConfig(swaggerDoc, itemUri, methodConfig.Responses), } uriList = append(uriList, uriResult) } @@ -133,3 +133,44 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def return res } + +// buildSwagger2ResultConfig 构建响应结果配置 +func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultConfig map[string]*define.SwaggerPathConfigResponse) []*define.ResultConfig { + res := make([]*define.ResultConfig, 0) + if nil == resultConfig || len(resultConfig) == 0 { + return res + } + if _, exist := resultConfig["200"]; !exist { + result204Config := resultConfig["204"] + resultConfig["200"] = result204Config + } + + if nil == resultConfig["200"] { + return res + } + definitionsKey := "" + if swaggerDoc.Responses == nil { + definitionsKey = GetRealDefinitionsKey(resultConfig["200"].Schema.Ref) + } else { + responseKey := GetRealResponseKey(resultConfig["200"].Ref) + 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 { + // 不是引用类型, 直接定义的具体类型 + res = append(res, &define.ResultConfig{ + Location: consts.ResponseDataLocationBody.String(), + Path: "", + Type: "", + Title: "", + Description: "", + }) + } + + return nil +} -- 2.36.6 From cc4ef13e23142ef65894ff6f4215fd2bbd78442f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 25 Dec 2024 11:55:22 +0800 Subject: [PATCH 11/14] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E7=9A=84=E8=BF=94=E5=9B=9E=E7=BB=93=E6=9E=9C=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9C=BA=E6=9E=84=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 19 +++++++++++++-- go.mod | 4 ++-- go.sum | 4 ++++ swagger.go | 68 +++++++++++++++++++++++++++++++++++++++--------------- 4 files changed, 72 insertions(+), 23 deletions(-) diff --git a/common.go b/common.go index de1731d..7cd76eb 100644 --- a/common.go +++ b/common.go @@ -8,6 +8,7 @@ package api_doc import ( + "fmt" "git.zhangdeman.cn/gateway/api-doc/define" "git.zhangdeman.cn/zhangdeman/consts" "strings" @@ -39,12 +40,12 @@ func GetUriPathParamList(uriPath string) []*define.ParamConfig { return result } -// GetParamType 将文档配置的数据类型转换为归一化处理后的数据类型 +// GetDataType 将文档配置的数据类型转换为归一化处理后的数据类型 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:52 2024/12/24 -func GetParamType(docParamType string, formatType string) consts.DataType { +func GetDataType(docParamType string, formatType string) consts.DataType { docParamType = strings.ToLower(docParamType) formatType = strings.ToLower(formatType) if len(formatType) == 0 { @@ -60,6 +61,10 @@ func GetParamType(docParamType string, formatType string) consts.DataType { 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 @@ -105,3 +110,13 @@ func GetRealDefinitionsKey(ref string) string { 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 +} diff --git a/go.mod b/go.mod index f5f5fea..396f4ce 100644 --- a/go.mod +++ b/go.mod @@ -3,10 +3,10 @@ module git.zhangdeman.cn/gateway/api-doc go 1.22.2 require ( - git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701 + 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 - github.com/tidwall/gjson v1.16.0 + github.com/tidwall/gjson v1.18.0 ) require ( diff --git a/go.sum b/go.sum index 38690da..7301eb6 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701 h1:G+lGQmjMOBWGspZfijZvenGUAKpjBBrkRXLg3+GZp0U= git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k= +git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241225030757-c00354fe4630 h1:KTp27pHr25X5khTi4B/OdFv/34UWkq6sgDfz5aBtj74= +git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241225030757-c00354fe4630/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/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U= git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI= @@ -28,6 +30,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT 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= diff --git a/swagger.go b/swagger.go index e9fdb8a..c197b4f 100644 --- a/swagger.go +++ b/swagger.go @@ -99,7 +99,7 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def paramConfigBuildConfig := &define.ParamConfig{ Location: GetParamLocation(paramConfig.In).String(), Path: paramConfig.Name, - Type: GetParamType(paramConfig.Type, paramConfig.Format).String(), + Type: GetDataType(paramConfig.Type, paramConfig.Format).String(), Title: paramConfig.Name, Description: paramConfig.Description, Required: paramConfig.Required, @@ -122,7 +122,7 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def paramConfigBuildConfig := &define.ParamConfig{ Location: GetParamLocation(paramConfig.In).String(), Path: paramName, - Type: GetParamType(paramMoreConfig.Type, "").String(), + Type: GetDataType(paramMoreConfig.Type, "").String(), Title: paramMoreConfig.Description, Description: paramMoreConfig.Description, Required: requiredTable[paramName], @@ -140,19 +140,26 @@ func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultCon if nil == resultConfig || len(resultConfig) == 0 { return res } - if _, exist := resultConfig["200"]; !exist { - result204Config := resultConfig["204"] - resultConfig["200"] = result204Config - } - - if nil == resultConfig["200"] { + successResponseConfig := GetSuccessResponseConfig(resultConfig) + if nil == successResponseConfig { return res } definitionsKey := "" if swaggerDoc.Responses == nil { - definitionsKey = GetRealDefinitionsKey(resultConfig["200"].Schema.Ref) + definitionsKey = successResponseConfig.Schema.Ref } else { - responseKey := GetRealResponseKey(resultConfig["200"].Ref) + 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 { @@ -163,14 +170,37 @@ func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultCon } if len(definitionsKey) == 0 { // 不是引用类型, 直接定义的具体类型 - res = append(res, &define.ResultConfig{ - Location: consts.ResponseDataLocationBody.String(), - Path: "", - Type: "", - Title: "", - Description: "", - }) + responseKey := GetRealResponseKey(successResponseConfig.Ref) + responseTypeDefine := swaggerDoc.Responses[responseKey] + if nil == responseTypeDefine.Schema { + // 204 场景下,可能没有响应body + res = append(res, &define.ResultConfig{ + Location: consts.ResponseDataLocationBody.String(), + Path: consts.ResponseDataLocationBodyRoot.String(), + Type: consts.DataTypeAny.String(), + Title: "response body", + Description: responseTypeDefine.Description, + }) + } else { + res = append(res, &define.ResultConfig{ + Location: consts.ResponseDataLocationBody.String(), + Path: consts.ResponseDataLocationBodyRoot.String(), + Type: GetDataType(responseTypeDefine.Schema.Type, "").String(), + Title: "response body", + Description: responseTypeDefine.Description, + }) + } + } 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: responseKeyConfig.Description, + }) + } } - - return nil + return res } -- 2.36.6 From f58f8da72205e65e5ddedc993157964e9de8fefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 25 Dec 2024 12:04:30 +0800 Subject: [PATCH 12/14] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- parser_test.go | 4 +++- swagger.go | 32 ++++++++++++++------------------ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/parser_test.go b/parser_test.go index 149598a..1bcfa94 100644 --- a/parser_test.go +++ b/parser_test.go @@ -11,6 +11,7 @@ import ( "encoding/json" "fmt" "git.zhangdeman.cn/gateway/api-doc/define" + "git.zhangdeman.cn/zhangdeman/serialize" "os" "os/user" "testing" @@ -35,5 +36,6 @@ func Test_parser_Openapi3(t *testing.T) { func TestParseForSwagger(t *testing.T) { docUrl := "https://git.zhangdeman.cn/swagger.v1.json" - _, _ = Parse(docUrl) + res, _ := Parse(docUrl) + serialize.JSON.ConsoleOutput(res) } diff --git a/swagger.go b/swagger.go index c197b4f..b5d35fe 100644 --- a/swagger.go +++ b/swagger.go @@ -123,7 +123,7 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def Location: GetParamLocation(paramConfig.In).String(), Path: paramName, Type: GetDataType(paramMoreConfig.Type, "").String(), - Title: paramMoreConfig.Description, + Title: paramName, Description: paramMoreConfig.Description, Required: requiredTable[paramName], } @@ -172,24 +172,20 @@ func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultCon // 不是引用类型, 直接定义的具体类型 responseKey := GetRealResponseKey(successResponseConfig.Ref) responseTypeDefine := swaggerDoc.Responses[responseKey] - if nil == responseTypeDefine.Schema { - // 204 场景下,可能没有响应body - res = append(res, &define.ResultConfig{ - Location: consts.ResponseDataLocationBody.String(), - Path: consts.ResponseDataLocationBodyRoot.String(), - Type: consts.DataTypeAny.String(), - Title: "response body", - Description: responseTypeDefine.Description, - }) + responseType := "" + if nil != responseTypeDefine.Schema { + // 204 等场景下,可能没有响应body + responseType = consts.DataTypeAny.String() } else { - res = append(res, &define.ResultConfig{ - Location: consts.ResponseDataLocationBody.String(), - Path: consts.ResponseDataLocationBodyRoot.String(), - Type: GetDataType(responseTypeDefine.Schema.Type, "").String(), - Title: "response body", - Description: responseTypeDefine.Description, - }) + responseType = GetDataType(responseTypeDefine.Schema.Type, "").String() } + res = append(res, &define.ResultConfig{ + Location: consts.ResponseDataLocationBody.String(), + Path: consts.ResponseDataLocationBodyRoot.String(), + Type: responseType, + Title: "response body", + Description: "response body", + }) } else { responseTypeDefine := swaggerDoc.Definitions[definitionsKey] for responseKey, responseKeyConfig := range responseTypeDefine.Properties { @@ -198,7 +194,7 @@ func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultCon Path: responseKey, Type: GetDataType(responseKeyConfig.Type, "").String(), Title: responseKey, - Description: responseKeyConfig.Description, + Description: responseKey, }) } } -- 2.36.6 From e70634a3183de7a5cde8b7e0060d1674c397191d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 25 Dec 2024 14:38:08 +0800 Subject: [PATCH 13/14] =?UTF-8?q?=E5=8F=82=E6=95=B0=20+=20=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E5=80=BC=E6=94=AF=E6=8C=81=E8=87=AA=E5=8A=A8=E5=B1=95?= =?UTF-8?q?=E5=BC=80=E4=B8=80=E5=B1=82=E6=95=B0=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 47 ++++++++++++++++++++++++++++++++++++++++++++++- swagger.go | 20 +++++++++++++++----- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/common.go b/common.go index 7cd76eb..34ec72f 100644 --- a/common.go +++ b/common.go @@ -74,7 +74,7 @@ func GetDataType(docParamType string, formatType string) consts.DataType { return consts.DataTypeSliceAny } default: - return consts.DataTypeMapStrAny + return consts.DataTypeAny } } @@ -120,3 +120,48 @@ func GetSuccessResponseConfig(resultConfig map[string]*define.SwaggerPathConfigR } 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 +} diff --git a/swagger.go b/swagger.go index b5d35fe..447a5ba 100644 --- a/swagger.go +++ b/swagger.go @@ -57,7 +57,7 @@ func buildUriList(swaggerDoc *define.Swagger) ([]*define.UriBaseConfig, error) { Summary: methodConfig.Summary, Description: methodConfig.Description, ParamList: buildSwagger2ParamConfig(swaggerDoc, methodConfig.Parameters), - ResultList: buildSwagger2ResultConfig(swaggerDoc, itemUri, methodConfig.Responses), + ResultList: buildSwagger2ResultConfig(swaggerDoc, methodConfig.Responses), } uriList = append(uriList, uriResult) } @@ -128,6 +128,10 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def 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)...) + } } } @@ -135,7 +139,7 @@ func buildSwagger2ParamConfig(swaggerDoc *define.Swagger, paramConfigList []*def } // buildSwagger2ResultConfig 构建响应结果配置 -func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultConfig map[string]*define.SwaggerPathConfigResponse) []*define.ResultConfig { +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 @@ -173,19 +177,25 @@ func buildSwagger2ResultConfig(swaggerDoc *define.Swagger, uri string, resultCon responseKey := GetRealResponseKey(successResponseConfig.Ref) responseTypeDefine := swaggerDoc.Responses[responseKey] responseType := "" - if nil != responseTypeDefine.Schema { + schemaType := "" + if nil == responseTypeDefine.Schema { // 204 等场景下,可能没有响应body responseType = consts.DataTypeAny.String() } else { + schemaType = responseTypeDefine.Schema.Type responseType = GetDataType(responseTypeDefine.Schema.Type, "").String() } - res = append(res, &define.ResultConfig{ + 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 { -- 2.36.6 From 368fb02efccce5b9948adbc69a27ba46258f20a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 25 Dec 2024 14:59:14 +0800 Subject: [PATCH 14/14] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E7=B1=BB=E5=8F=82=E6=95=B0=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common.go | 2 +- define/generate.go | 9 +++++---- define/swagger.go | 17 +++++++++-------- swagger.go | 29 +++++++++++++++++++++++++---- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/common.go b/common.go index 34ec72f..469b561 100644 --- a/common.go +++ b/common.go @@ -57,7 +57,7 @@ func GetDataType(docParamType string, formatType string) consts.DataType { return consts.DataTypeInt } return consts.DataTypeUint - case "string": + case "string", "apikey": return consts.DataTypeString case "object": return consts.DataTypeMapStrAny diff --git a/define/generate.go b/define/generate.go index 7f66fcf..7ecfe1b 100644 --- a/define/generate.go +++ b/define/generate.go @@ -15,10 +15,11 @@ import "regexp" // // 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"` // 接口列表 + 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 添加接口时的基础配置 diff --git a/define/swagger.go b/define/swagger.go index 1fbfab2..096159a 100644 --- a/define/swagger.go +++ b/define/swagger.go @@ -101,14 +101,15 @@ type SwaggerDefinitionPropertyItem struct { // // Date : 16:12 2024/4/19 type Swagger struct { - Schemes []string `json:"schemes"` - Swagger string `json:"swagger"` // swagger版本 - 2.0 - Host string `json:"host"` // 服务域名 - BasePath string `json:"basePath"` // 基础path - Info Info `json:"info"` // 文档描述信息 - Paths map[string]map[string]*SwaggerPathConfig `json:"paths"` // 接口列表 : 接口 => 请求方法 => 请求配置 - Definitions map[string]*SwaggerDefinition `json:"definitions"` // 数据定义 - Responses map[string]*SwaggerPathConfigResponse `json:"responses"` // 响应结构列表 + Schemes []string `json:"schemes"` + Swagger string `json:"swagger"` // swagger版本 - 2.0 + Host string `json:"host"` // 服务域名 + BasePath string `json:"basePath"` // 基础path + Info Info `json:"info"` // 文档描述信息 + Paths map[string]map[string]*SwaggerPathConfig `json:"paths"` // 接口列表 : 接口 => 请求方法 => 请求配置 + Definitions map[string]*SwaggerDefinition `json:"definitions"` // 数据定义 + Responses map[string]*SwaggerPathConfigResponse `json:"responses"` // 响应结构列表 + SecurityDefinitions map[string]*SwaggerPathConfigParameter `json:"securityDefinitions"` // 安全选项 } // SwaggerInput ... diff --git a/swagger.go b/swagger.go index 447a5ba..5df17fe 100644 --- a/swagger.go +++ b/swagger.go @@ -31,17 +31,38 @@ func ParseSwagger2(docContent []byte) (*define.DocParseResult, error) { 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), + 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) -- 2.36.6