openapi格式的文档基础生成 #3
172
generate.go
172
generate.go
@ -184,6 +184,81 @@ func (g *Generate) AddApiFromInAndOut(paramType reflect.Type, resultType reflect
|
|||||||
if _, exist := g.docData.Paths[baseCfg.Uri]; !exist {
|
if _, exist := g.docData.Paths[baseCfg.Uri]; !exist {
|
||||||
g.docData.Paths[baseCfg.Uri] = &define.PathConfig{}
|
g.docData.Paths[baseCfg.Uri] = &define.PathConfig{}
|
||||||
}
|
}
|
||||||
|
// 接口文档初始化
|
||||||
|
cfg := g.getApiDocBaseCfg(baseCfg, paramType)
|
||||||
|
paramMethod := []string{
|
||||||
|
http.MethodGet, http.MethodHead, http.MethodConnect, http.MethodOptions, http.MethodTrace,
|
||||||
|
}
|
||||||
|
if wrapper.ArrayType(paramMethod).Has(baseCfg.Method) >= 0 {
|
||||||
|
cfg.RequestBody = nil // get类请求没有request body
|
||||||
|
// 参数解析
|
||||||
|
g.ParseReadConfigParam(baseCfg, cfg, paramType)
|
||||||
|
} else {
|
||||||
|
// post类解析
|
||||||
|
paramSchemaName := g.AddComponentsSchema("", paramType.PkgPath(), paramType)
|
||||||
|
for _, itemType := range baseCfg.ContentType {
|
||||||
|
cfg.RequestBody.Content[itemType] = &define.Media{
|
||||||
|
Schema: &define.Schema{
|
||||||
|
Ref: g.getSchemaRef(paramSchemaName),
|
||||||
|
},
|
||||||
|
Example: "",
|
||||||
|
Examples: nil,
|
||||||
|
Encoding: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 无论什么请求, 对于result解析逻辑一致
|
||||||
|
resultSchemaName := g.AddComponentsSchema("", resultType.PkgPath(), resultType)
|
||||||
|
for _, itemOutputType := range baseCfg.OutputContentType {
|
||||||
|
cfg.Responses[fmt.Sprintf("%v", http.StatusOK)].Content[itemOutputType] = &define.Media{
|
||||||
|
Schema: &define.Schema{
|
||||||
|
Ref: g.getSchemaRef(resultSchemaName),
|
||||||
|
},
|
||||||
|
Example: "",
|
||||||
|
Examples: nil,
|
||||||
|
Encoding: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.setApiDoc(baseCfg, cfg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setApiDoc 设置文档配置
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 16:13 2025/2/14
|
||||||
|
func (g *Generate) setApiDoc(baseCfg *define.UriBaseConfig, apiDocCfg *define.PathItemOperationConfig) {
|
||||||
|
switch baseCfg.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Get = apiDocCfg
|
||||||
|
case http.MethodHead:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Head = apiDocCfg
|
||||||
|
case http.MethodPost:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Post = apiDocCfg
|
||||||
|
case http.MethodPut:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Put = apiDocCfg
|
||||||
|
case http.MethodPatch:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Patch = apiDocCfg
|
||||||
|
case http.MethodDelete:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Delete = apiDocCfg
|
||||||
|
case http.MethodConnect:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Connect = apiDocCfg
|
||||||
|
case http.MethodOptions:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Options = apiDocCfg
|
||||||
|
case http.MethodTrace:
|
||||||
|
g.docData.Paths[baseCfg.Uri].Trace = apiDocCfg
|
||||||
|
default:
|
||||||
|
panic("unknown method: " + baseCfg.Method)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getApiDocBaseCfg 获取接口文档的基础配置
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 16:10 2025/2/14
|
||||||
|
func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType reflect.Type) *define.PathItemOperationConfig {
|
||||||
defaultPkgPath := wrapper.String(strings.TrimLeft(baseCfg.Uri, "/")).SnakeCaseToCamel()
|
defaultPkgPath := wrapper.String(strings.TrimLeft(baseCfg.Uri, "/")).SnakeCaseToCamel()
|
||||||
cfg := &define.PathItemOperationConfig{
|
cfg := &define.PathItemOperationConfig{
|
||||||
Tags: baseCfg.TagList,
|
Tags: baseCfg.TagList,
|
||||||
@ -227,63 +302,7 @@ func (g *Generate) AddApiFromInAndOut(paramType reflect.Type, resultType reflect
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paramMethod := []string{
|
return cfg
|
||||||
http.MethodGet, http.MethodHead, http.MethodConnect, http.MethodOptions, http.MethodTrace,
|
|
||||||
}
|
|
||||||
if wrapper.ArrayType(paramMethod).Has(baseCfg.Method) >= 0 {
|
|
||||||
cfg.RequestBody = nil // get类请求没有request body
|
|
||||||
// Get类请求, TODO : get类解析
|
|
||||||
// 参数解析
|
|
||||||
g.ParseReadConfigParam(baseCfg, cfg, paramType)
|
|
||||||
} else {
|
|
||||||
// post类解析
|
|
||||||
paramSchemaName := g.AddComponentsSchema("", paramType.PkgPath(), paramType)
|
|
||||||
for _, itemType := range baseCfg.ContentType {
|
|
||||||
cfg.RequestBody.Content[itemType] = &define.Media{
|
|
||||||
Schema: &define.Schema{
|
|
||||||
Ref: g.getSchemaRef(paramSchemaName),
|
|
||||||
},
|
|
||||||
Example: "",
|
|
||||||
Examples: nil,
|
|
||||||
Encoding: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 无论什么请求, 对于result解析逻辑一致
|
|
||||||
resultSchemaName := g.AddComponentsSchema("", resultType.PkgPath(), resultType)
|
|
||||||
for _, itemOutputType := range baseCfg.OutputContentType {
|
|
||||||
cfg.Responses[fmt.Sprintf("%v", http.StatusOK)].Content[itemOutputType] = &define.Media{
|
|
||||||
Schema: &define.Schema{
|
|
||||||
Ref: g.getSchemaRef(resultSchemaName),
|
|
||||||
},
|
|
||||||
Example: "",
|
|
||||||
Examples: nil,
|
|
||||||
Encoding: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch baseCfg.Method {
|
|
||||||
case http.MethodGet:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Get = cfg
|
|
||||||
case http.MethodHead:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Head = cfg
|
|
||||||
case http.MethodPost:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Post = cfg
|
|
||||||
case http.MethodPut:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Put = cfg
|
|
||||||
case http.MethodPatch:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Patch = cfg
|
|
||||||
case http.MethodDelete:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Delete = cfg
|
|
||||||
case http.MethodConnect:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Connect = cfg
|
|
||||||
case http.MethodOptions:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Options = cfg
|
|
||||||
case http.MethodTrace:
|
|
||||||
g.docData.Paths[baseCfg.Uri].Trace = cfg
|
|
||||||
default:
|
|
||||||
panic("unknown method: " + baseCfg.Method)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseReadConfigParam 解析get类请求参数
|
// ParseReadConfigParam 解析get类请求参数
|
||||||
@ -298,6 +317,9 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
|
|||||||
if inputType.Kind() != reflect.Struct {
|
if inputType.Kind() != reflect.Struct {
|
||||||
panic(requestCfg.Uri + " : request param not struct")
|
panic(requestCfg.Uri + " : request param not struct")
|
||||||
}
|
}
|
||||||
|
if nil == baseReqCfg.Parameters {
|
||||||
|
baseReqCfg.Parameters = make([]*define.PathConfigParameter, 0)
|
||||||
|
}
|
||||||
for i := 0; i < inputType.NumField(); i++ {
|
for i := 0; i < inputType.NumField(); i++ {
|
||||||
propertyName := ParseStructField.GetParamName(inputType.Field(i))
|
propertyName := ParseStructField.GetParamName(inputType.Field(i))
|
||||||
if propertyName == "-" {
|
if propertyName == "-" {
|
||||||
@ -315,14 +337,28 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
|
|||||||
fieldType.Kind() == reflect.Slice {
|
fieldType.Kind() == reflect.Slice {
|
||||||
if convertType := g.realBaseType2SwaggerType(fieldType.String()); !strings.HasPrefix(convertType, "[]") && convertType != inputType.Field(i).Type.Kind().String() {
|
if convertType := g.realBaseType2SwaggerType(fieldType.String()); !strings.HasPrefix(convertType, "[]") && convertType != inputType.Field(i).Type.Kind().String() {
|
||||||
// 针对基础类型指针
|
// 针对基础类型指针
|
||||||
|
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
|
||||||
|
Name: ParseStructField.GetParamName(inputType.Field(i)),
|
||||||
|
In: consts.SwaggerParameterInQuery,
|
||||||
|
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||||
|
Required: ValidateRule.IsRequired(inputType.Field(i)),
|
||||||
|
Deprecated: ParseStructField.Deprecated(inputType.Field(i)),
|
||||||
|
Schema: &define.Schema{
|
||||||
|
Type: g.realBaseType2SwaggerType(inputType.Field(i).Type.String()),
|
||||||
|
Items: nil,
|
||||||
|
Ref: "",
|
||||||
|
Format: realInputTypeFormat,
|
||||||
|
},
|
||||||
|
AllowEmptyValue: false,
|
||||||
|
Style: "",
|
||||||
|
Explode: false,
|
||||||
|
AllowReserved: false,
|
||||||
|
Ref: "",
|
||||||
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if nil == g.docData.Paths[requestCfg.Uri].Get {
|
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
|
||||||
g.docData.Paths[requestCfg.Uri].Get = &define.PathItemOperationConfig{}
|
|
||||||
}
|
|
||||||
g.docData.Paths[requestCfg.Uri].Get.Parameters = append(g.docData.Paths[requestCfg.Uri].Get.Parameters, &define.PathConfigParameter{
|
|
||||||
Name: ParseStructField.GetParamName(inputType.Field(i)),
|
Name: ParseStructField.GetParamName(inputType.Field(i)),
|
||||||
In: consts.SwaggerParameterInQuery,
|
In: consts.SwaggerParameterInQuery,
|
||||||
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
Description: ParseStructField.GetParamDesc(inputType.Field(i)),
|
||||||
@ -342,6 +378,18 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switch requestCfg.Method {
|
||||||
|
case http.MethodGet:
|
||||||
|
g.docData.Paths[requestCfg.Uri].Get = baseReqCfg
|
||||||
|
case http.MethodHead:
|
||||||
|
g.docData.Paths[requestCfg.Uri].Head = baseReqCfg
|
||||||
|
case http.MethodConnect:
|
||||||
|
g.docData.Paths[requestCfg.Uri].Connect = baseReqCfg
|
||||||
|
case http.MethodOptions:
|
||||||
|
g.docData.Paths[requestCfg.Uri].Options = baseReqCfg
|
||||||
|
case http.MethodTrace:
|
||||||
|
g.docData.Paths[requestCfg.Uri].Trace = baseReqCfg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddComponentsSchema 添加schema
|
// AddComponentsSchema 添加schema
|
||||||
|
@ -45,6 +45,11 @@ func Test_parser_Openapi3(t *testing.T) {
|
|||||||
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"`
|
||||||
}
|
}
|
||||||
|
type UserHead struct {
|
||||||
|
Meta `json:"-" deprecated:"false" path:"/user/detail/head/{put_user_id}" method:"HEAD" 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"`
|
||||||
|
}
|
||||||
type List struct {
|
type List struct {
|
||||||
Total int64 `json:"total" binding:"required"`
|
Total int64 `json:"total" binding:"required"`
|
||||||
UserList []User `json:"user_list"`
|
UserList []User `json:"user_list"`
|
||||||
@ -54,11 +59,18 @@ func Test_parser_Openapi3(t *testing.T) {
|
|||||||
var fd UserDelete
|
var fd UserDelete
|
||||||
var up UserPut
|
var up UserPut
|
||||||
var ug UserGet
|
var ug UserGet
|
||||||
|
var uh UserHead
|
||||||
g := NewOpenapiDoc(nil, []*define.ServerItem{
|
g := NewOpenapiDoc(nil, []*define.ServerItem{
|
||||||
&define.ServerItem{
|
&define.ServerItem{
|
||||||
Url: "http://127.0.0.1/v1",
|
Url: "http://127.0.0.1/v1",
|
||||||
Description: "v1接口",
|
Description: "v1接口",
|
||||||
Variables: nil,
|
Variables: map[string]*define.ServerItemVariable{
|
||||||
|
"test": &define.ServerItemVariable{
|
||||||
|
Default: "123456",
|
||||||
|
Description: "1111",
|
||||||
|
Enum: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
&define.ServerItem{
|
&define.ServerItem{
|
||||||
Url: "http://127.0.0.1/v2",
|
Url: "http://127.0.0.1/v2",
|
||||||
@ -70,6 +82,7 @@ func Test_parser_Openapi3(t *testing.T) {
|
|||||||
g.AddApiFromInAndOut(reflect.TypeOf(fd), reflect.TypeOf(o))
|
g.AddApiFromInAndOut(reflect.TypeOf(fd), reflect.TypeOf(o))
|
||||||
g.AddApiFromInAndOut(reflect.TypeOf(up), reflect.TypeOf(o))
|
g.AddApiFromInAndOut(reflect.TypeOf(up), reflect.TypeOf(o))
|
||||||
g.AddApiFromInAndOut(reflect.TypeOf(ug), reflect.TypeOf(o))
|
g.AddApiFromInAndOut(reflect.TypeOf(ug), reflect.TypeOf(o))
|
||||||
|
g.AddApiFromInAndOut(reflect.TypeOf(uh), reflect.TypeOf(o))
|
||||||
byteData, _ := json.Marshal(g.docData)
|
byteData, _ := json.Marshal(g.docData)
|
||||||
fmt.Println(string(byteData))
|
fmt.Println(string(byteData))
|
||||||
}
|
}
|
||||||
|
@ -139,5 +139,9 @@ func (psf parseStructField) Summary(structField reflect.StructField) string {
|
|||||||
return tagVal
|
return tagVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return psf.GetParamName(structField)
|
paramName := psf.GetParamName(structField)
|
||||||
|
if paramName == "-" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return paramName
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user