优化接口基础信息解析 + 支持设置接口是否弃用
This commit is contained in:
parent
45a25e0018
commit
e2da9231a1
@ -37,6 +37,8 @@ type UriBaseConfig struct {
|
|||||||
Description string `json:"description"` // 接口详细描述
|
Description string `json:"description"` // 接口详细描述
|
||||||
ParamList []*ParamConfig `json:"param_list"` // 参数列表
|
ParamList []*ParamConfig `json:"param_list"` // 参数列表
|
||||||
ResultList []*ResultConfig `json:"result_list"` // 返回值列表
|
ResultList []*ResultConfig `json:"result_list"` // 返回值列表
|
||||||
|
Deprecated bool `json:"deprecated"` // 是否弃用
|
||||||
|
OutputStrict bool `json:"output_strict"` // 严格模式
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParamConfig 参数配置
|
// ParamConfig 参数配置
|
||||||
|
@ -21,4 +21,18 @@ const (
|
|||||||
TagDescription = "description"
|
TagDescription = "description"
|
||||||
TagD = "d"
|
TagD = "d"
|
||||||
TagDefault = "default"
|
TagDefault = "default"
|
||||||
|
TagDeprecated = "deprecated"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TagNamePath = "path" // 接口的请求路径
|
||||||
|
TagNameMethod = "method" // 接口的请求方法
|
||||||
|
TagNameUriTag = "tag" // 接口的tag
|
||||||
|
TagNameDesc = "desc" // 接口的描述
|
||||||
|
TagNameOutputStrict = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map,非严格模式返回任意值
|
||||||
|
TagNameBinding = "binding" // gin 内置的验证规则tag
|
||||||
|
TagNameValidate = "validate" // validator v10 默认的验证规则tag
|
||||||
|
TagNameErrMsg = "err" // 验证失败错误信息tag
|
||||||
|
TagNameContentType = "content_type"
|
||||||
|
TagNameOutputContentType = "output_content_type"
|
||||||
)
|
)
|
||||||
|
20
define/uri.go
Normal file
20
define/uri.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Package define ...
|
||||||
|
//
|
||||||
|
// Description : define ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2025-02-13 21:29
|
||||||
|
package define
|
||||||
|
|
||||||
|
// UriConfig 接口基础配置
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 21:29 2025/2/13
|
||||||
|
type UriConfig struct {
|
||||||
|
Path string `json:"path"` // 接口路由, 必须配置
|
||||||
|
RequestMethod string `json:"request_method"` // 接口请求方法, 必须配置
|
||||||
|
TagList []string `json:"tag_list"` // 接口分组
|
||||||
|
Desc string `json:"desc"` // 接口描述
|
||||||
|
}
|
55
generate.go
55
generate.go
@ -170,7 +170,8 @@ func (g *Generate) AddApi(baseCfg *define.UriBaseConfig, paramList []*define.Par
|
|||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
//
|
//
|
||||||
// Date : 14:22 2025/2/9
|
// Date : 14:22 2025/2/9
|
||||||
func (g *Generate) AddApiFromInAndOut(baseCfg *define.UriBaseConfig, paramType reflect.Type, resultType reflect.Type) error {
|
func (g *Generate) AddApiFromInAndOut(paramType reflect.Type, resultType reflect.Type) error {
|
||||||
|
baseCfg := g.parseBaseUriConfig(paramType)
|
||||||
if nil == baseCfg {
|
if nil == baseCfg {
|
||||||
return errors.New("baseCfg is nil")
|
return errors.New("baseCfg is nil")
|
||||||
}
|
}
|
||||||
@ -220,7 +221,7 @@ func (g *Generate) AddApiFromInAndOut(baseCfg *define.UriBaseConfig, paramType r
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Callbacks: nil,
|
Callbacks: nil,
|
||||||
Deprecated: false,
|
Deprecated: baseCfg.Deprecated,
|
||||||
Security: nil,
|
Security: nil,
|
||||||
Servers: nil,
|
Servers: nil,
|
||||||
}
|
}
|
||||||
@ -276,6 +277,10 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
|||||||
inputNameArr := strings.Split(inputType.Name(), ".")
|
inputNameArr := strings.Split(inputType.Name(), ".")
|
||||||
inputName := inputNameArr[len(inputNameArr)-1]
|
inputName := inputNameArr[len(inputNameArr)-1]
|
||||||
schemaName := strings.ReplaceAll(pkgPath+"."+inputName, "/", "-")
|
schemaName := strings.ReplaceAll(pkgPath+"."+inputName, "/", "-")
|
||||||
|
if schemaName == "-" {
|
||||||
|
// 忽略的属性
|
||||||
|
return schemaName
|
||||||
|
}
|
||||||
if _, exist := g.docData.Components.Schemas[schemaName]; exist {
|
if _, exist := g.docData.Components.Schemas[schemaName]; exist {
|
||||||
// 已存在, 无需重复生成
|
// 已存在, 无需重复生成
|
||||||
return schemaName
|
return schemaName
|
||||||
@ -326,6 +331,10 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
|||||||
}
|
}
|
||||||
// g.docData.Components.Schemas[schemaName].Ref = consts.SwaggerDataTypeObject
|
// g.docData.Components.Schemas[schemaName].Ref = consts.SwaggerDataTypeObject
|
||||||
for i := 0; i < inputType.NumField(); i++ {
|
for i := 0; i < inputType.NumField(); i++ {
|
||||||
|
propertyName := ParseStructField.GetParamName(inputType.Field(i))
|
||||||
|
if propertyName == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if inputType.Field(i).Type.Kind() == reflect.Ptr ||
|
if inputType.Field(i).Type.Kind() == reflect.Ptr ||
|
||||||
inputType.Field(i).Type.Kind() == reflect.Struct ||
|
inputType.Field(i).Type.Kind() == reflect.Struct ||
|
||||||
inputType.Field(i).Type.Kind() == reflect.Map ||
|
inputType.Field(i).Type.Kind() == reflect.Map ||
|
||||||
@ -333,7 +342,7 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
|||||||
inputType.Field(i).Type.Kind() == reflect.Slice {
|
inputType.Field(i).Type.Kind() == reflect.Slice {
|
||||||
if convertType := g.realBaseType2SwaggerType(inputType.Field(i).Type.String()); !strings.HasPrefix(convertType, "[]") && convertType != inputType.Field(i).Type.Kind().String() {
|
if convertType := g.realBaseType2SwaggerType(inputType.Field(i).Type.String()); !strings.HasPrefix(convertType, "[]") && convertType != inputType.Field(i).Type.Kind().String() {
|
||||||
// 针对基础类型指针
|
// 针对基础类型指针
|
||||||
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(inputType.Field(i))] = &define.Property{
|
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
|
||||||
Type: g.realBaseType2SwaggerType(convertType),
|
Type: g.realBaseType2SwaggerType(convertType),
|
||||||
Format: inputType.Field(i).Type.String(),
|
Format: inputType.Field(i).Type.String(),
|
||||||
Default: ParseStructField.GetDefaultValue(inputType.Field(i)),
|
Default: ParseStructField.GetDefaultValue(inputType.Field(i)),
|
||||||
@ -343,7 +352,7 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
|||||||
}
|
}
|
||||||
if inputType.Field(i).Type.Kind() == reflect.Struct ||
|
if inputType.Field(i).Type.Kind() == reflect.Struct ||
|
||||||
inputType.Field(i).Type.Kind() == reflect.Map {
|
inputType.Field(i).Type.Kind() == reflect.Map {
|
||||||
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(inputType.Field(i))] = &define.Property{
|
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
|
||||||
Type: consts.SwaggerDataTypeObject,
|
Type: consts.SwaggerDataTypeObject,
|
||||||
Format: inputType.Field(i).Type.String(),
|
Format: inputType.Field(i).Type.String(),
|
||||||
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||||
@ -351,7 +360,7 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
|||||||
}
|
}
|
||||||
} else if inputType.Field(i).Type.Kind() == reflect.Array ||
|
} else if inputType.Field(i).Type.Kind() == reflect.Array ||
|
||||||
inputType.Field(i).Type.Kind() == reflect.Slice {
|
inputType.Field(i).Type.Kind() == reflect.Slice {
|
||||||
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(inputType.Field(i))] = &define.Property{
|
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
|
||||||
Type: consts.SwaggerDataTypeArray,
|
Type: consts.SwaggerDataTypeArray,
|
||||||
Format: inputType.Field(i).Type.String(),
|
Format: inputType.Field(i).Type.String(),
|
||||||
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||||
@ -363,11 +372,11 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
|||||||
} else if inputType.Field(i).Type.Kind() == reflect.Ptr {
|
} else if inputType.Field(i).Type.Kind() == reflect.Ptr {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
g.AddComponentsSchema(schemaName, ParseStructField.GetParamName(inputType.Field(i)), inputType.Field(i).Type)
|
g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(inputType.Field(i))] = &define.Property{
|
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
|
||||||
Type: g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
|
Type: g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
|
||||||
Format: inputType.Field(i).Type.String(),
|
Format: inputType.Field(i).Type.String(),
|
||||||
Default: ParseStructField.GetDefaultValue(inputType.Field(i)),
|
Default: ParseStructField.GetDefaultValue(inputType.Field(i)),
|
||||||
@ -475,3 +484,35 @@ func (g *Generate) setStructFieldProperty(schemaName string, structField reflect
|
|||||||
}
|
}
|
||||||
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(structField)].Enum = ValidateRule.Enum(structField)
|
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(structField)].Enum = ValidateRule.Enum(structField)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *Generate) parseBaseUriConfig(paramType reflect.Type) *define.UriBaseConfig {
|
||||||
|
// 解析meta信息
|
||||||
|
metaField, metaFieldExist := paramType.FieldByName("Meta")
|
||||||
|
if !metaFieldExist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
res := &define.UriBaseConfig{
|
||||||
|
Uri: "",
|
||||||
|
Method: "",
|
||||||
|
ContentType: nil,
|
||||||
|
OutputContentType: nil,
|
||||||
|
TagList: nil,
|
||||||
|
Summary: "",
|
||||||
|
Description: "",
|
||||||
|
ParamList: nil,
|
||||||
|
ResultList: nil,
|
||||||
|
Deprecated: false,
|
||||||
|
}
|
||||||
|
res.Uri = metaField.Tag.Get(define.TagNamePath)
|
||||||
|
res.Method = metaField.Tag.Get(define.TagNameMethod)
|
||||||
|
res.Description = metaField.Tag.Get(define.TagNameDesc)
|
||||||
|
res.TagList = strings.Split(metaField.Tag.Get(define.TagNameUriTag), ",")
|
||||||
|
// 解析第一个返回值, 要求必须是结构体或者是map
|
||||||
|
outputStrictModel := metaField.Tag.Get(define.TagNameOutputStrict)
|
||||||
|
res.OutputStrict = outputStrictModel == "1" || outputStrictModel == "true"
|
||||||
|
deprecated := metaField.Tag.Get(define.TagDeprecated)
|
||||||
|
res.Deprecated = deprecated == "1" || deprecated == "true"
|
||||||
|
res.ContentType = strings.Split(metaField.Tag.Get(define.TagNameContentType), ",")
|
||||||
|
res.OutputContentType = strings.Split(metaField.Tag.Get(define.TagNameOutputContentType), ",")
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
@ -10,13 +10,14 @@ package api_doc
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.zhangdeman.cn/gateway/api-doc/define"
|
|
||||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||||
"net/http"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Meta struct {
|
||||||
|
}
|
||||||
|
|
||||||
// Test_parser_Openapi3 测试数据结构定义正确性
|
// Test_parser_Openapi3 测试数据结构定义正确性
|
||||||
//
|
//
|
||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
@ -24,6 +25,7 @@ import (
|
|||||||
// Date : 17:55 2024/7/19
|
// Date : 17:55 2024/7/19
|
||||||
func Test_parser_Openapi3(t *testing.T) {
|
func Test_parser_Openapi3(t *testing.T) {
|
||||||
type User struct {
|
type User struct {
|
||||||
|
Meta `json:"-" deprecated:"true" path:"/user/detail" method:"POST" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"`
|
||||||
Name string `json:"name" d:"zhang" desc:"用户姓名" binding:"required"`
|
Name string `json:"name" d:"zhang" desc:"用户姓名" binding:"required"`
|
||||||
Age string `json:"age" d:"18" desc:"年龄" binding:"required,oneof=12 13 18 90"`
|
Age string `json:"age" d:"18" desc:"年龄" binding:"required,oneof=12 13 18 90"`
|
||||||
}
|
}
|
||||||
@ -31,22 +33,13 @@ func Test_parser_Openapi3(t *testing.T) {
|
|||||||
Total int64 `json:"total" binding:"required"`
|
Total int64 `json:"total" binding:"required"`
|
||||||
UserList []User `json:"user_list"`
|
UserList []User `json:"user_list"`
|
||||||
}
|
}
|
||||||
var l List
|
var o List
|
||||||
|
var f User
|
||||||
g := NewOpenapiDoc(nil, nil)
|
g := NewOpenapiDoc(nil, nil)
|
||||||
g.AddApiFromInAndOut(&define.UriBaseConfig{
|
g.AddApiFromInAndOut(reflect.TypeOf(f), reflect.TypeOf(o))
|
||||||
Uri: "/ent/user/detail",
|
|
||||||
Method: http.MethodPost,
|
|
||||||
ContentType: []string{"application/x-www-form-urlencoded"},
|
|
||||||
OutputContentType: []string{"application/yml", "application/json", "application/xml"},
|
|
||||||
TagList: []string{"测试文档生成"},
|
|
||||||
Summary: "测试接口",
|
|
||||||
Description: "",
|
|
||||||
ParamList: nil,
|
|
||||||
ResultList: nil,
|
|
||||||
}, reflect.TypeOf(l), reflect.TypeOf(l))
|
|
||||||
byteData, _ := json.Marshal(g.docData)
|
byteData, _ := json.Marshal(g.docData)
|
||||||
fmt.Println(string(byteData))
|
fmt.Println(string(byteData))
|
||||||
fmt.Println(g.parseSliceItem("", reflect.TypeOf(l)))
|
fmt.Println(g.parseSliceItem("", reflect.TypeOf(o)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseForSwagger(t *testing.T) {
|
func TestParseForSwagger(t *testing.T) {
|
||||||
|
@ -111,3 +111,18 @@ func (psf parseStructField) GetValidateRule(structField reflect.StructField) str
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated 是否弃用
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 21:12 2025/2/13
|
||||||
|
func (psf parseStructField) Deprecated(structField reflect.StructField) bool {
|
||||||
|
defaultTagList := []string{define.TagDeprecated}
|
||||||
|
for _, tag := range defaultTagList {
|
||||||
|
if tagVal, exist := structField.Tag.Lookup(tag); exist && (tagVal == "1" || strings.ToLower(tagVal) == "true") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user