优化接口基础信息解析 + 支持设置接口是否弃用
This commit is contained in:
parent
45a25e0018
commit
e2da9231a1
@ -37,6 +37,8 @@ type UriBaseConfig struct {
|
||||
Description string `json:"description"` // 接口详细描述
|
||||
ParamList []*ParamConfig `json:"param_list"` // 参数列表
|
||||
ResultList []*ResultConfig `json:"result_list"` // 返回值列表
|
||||
Deprecated bool `json:"deprecated"` // 是否弃用
|
||||
OutputStrict bool `json:"output_strict"` // 严格模式
|
||||
}
|
||||
|
||||
// ParamConfig 参数配置
|
||||
|
@ -21,4 +21,18 @@ const (
|
||||
TagDescription = "description"
|
||||
TagD = "d"
|
||||
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<白茶清欢>
|
||||
//
|
||||
// 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 {
|
||||
return errors.New("baseCfg is nil")
|
||||
}
|
||||
@ -220,7 +221,7 @@ func (g *Generate) AddApiFromInAndOut(baseCfg *define.UriBaseConfig, paramType r
|
||||
},
|
||||
},
|
||||
Callbacks: nil,
|
||||
Deprecated: false,
|
||||
Deprecated: baseCfg.Deprecated,
|
||||
Security: nil,
|
||||
Servers: nil,
|
||||
}
|
||||
@ -276,6 +277,10 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
||||
inputNameArr := strings.Split(inputType.Name(), ".")
|
||||
inputName := inputNameArr[len(inputNameArr)-1]
|
||||
schemaName := strings.ReplaceAll(pkgPath+"."+inputName, "/", "-")
|
||||
if schemaName == "-" {
|
||||
// 忽略的属性
|
||||
return schemaName
|
||||
}
|
||||
if _, exist := g.docData.Components.Schemas[schemaName]; exist {
|
||||
// 已存在, 无需重复生成
|
||||
return schemaName
|
||||
@ -326,6 +331,10 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
|
||||
}
|
||||
// g.docData.Components.Schemas[schemaName].Ref = consts.SwaggerDataTypeObject
|
||||
for i := 0; i < inputType.NumField(); i++ {
|
||||
propertyName := ParseStructField.GetParamName(inputType.Field(i))
|
||||
if propertyName == "-" {
|
||||
continue
|
||||
}
|
||||
if inputType.Field(i).Type.Kind() == reflect.Ptr ||
|
||||
inputType.Field(i).Type.Kind() == reflect.Struct ||
|
||||
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 {
|
||||
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),
|
||||
Format: inputType.Field(i).Type.String(),
|
||||
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 ||
|
||||
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,
|
||||
Format: inputType.Field(i).Type.String(),
|
||||
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 ||
|
||||
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,
|
||||
Format: inputType.Field(i).Type.String(),
|
||||
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 {
|
||||
g.AddComponentsSchema(schemaName, ParseStructField.GetParamName(inputType.Field(i)), inputType.Field(i).Type)
|
||||
g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type)
|
||||
}
|
||||
|
||||
} 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()),
|
||||
Format: inputType.Field(i).Type.String(),
|
||||
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)
|
||||
}
|
||||
|
||||
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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.zhangdeman.cn/gateway/api-doc/define"
|
||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Meta struct {
|
||||
}
|
||||
|
||||
// Test_parser_Openapi3 测试数据结构定义正确性
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
@ -24,6 +25,7 @@ import (
|
||||
// Date : 17:55 2024/7/19
|
||||
func Test_parser_Openapi3(t *testing.T) {
|
||||
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"`
|
||||
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"`
|
||||
UserList []User `json:"user_list"`
|
||||
}
|
||||
var l List
|
||||
var o List
|
||||
var f User
|
||||
g := NewOpenapiDoc(nil, nil)
|
||||
g.AddApiFromInAndOut(&define.UriBaseConfig{
|
||||
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))
|
||||
g.AddApiFromInAndOut(reflect.TypeOf(f), reflect.TypeOf(o))
|
||||
byteData, _ := json.Marshal(g.docData)
|
||||
fmt.Println(string(byteData))
|
||||
fmt.Println(g.parseSliceItem("", reflect.TypeOf(l)))
|
||||
fmt.Println(g.parseSliceItem("", reflect.TypeOf(o)))
|
||||
}
|
||||
|
||||
func TestParseForSwagger(t *testing.T) {
|
||||
|
@ -111,3 +111,18 @@ func (psf parseStructField) GetValidateRule(structField reflect.StructField) str
|
||||
}
|
||||
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