Merge pull request '支持匿名字段' (#9) from feature/fix_base_arr_anonymity_struct into master

Reviewed-on: #9
This commit is contained in:
白茶清欢 2025-02-18 14:07:24 +08:00
commit db15e16f99
5 changed files with 172 additions and 107 deletions

View File

@ -162,7 +162,9 @@ type Property struct {
// //
// Date : 17:13 2024/7/19 // Date : 17:13 2024/7/19
type PropertyXOf struct { type PropertyXOf struct {
Ref string `json:"$ref"` // 引用的结构描述 Type string `json:"type,omitempty"` // 基础类型
Format string `json:"format,omitempty"` // 真实类型
Ref string `json:"$ref,omitempty"` // 引用的结构描述
} }
// SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验 // SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验

View File

@ -270,7 +270,7 @@ func (g *Generate) getApiDocBaseCfg(baseCfg *define.UriBaseConfig, paramType ref
Summary: baseCfg.Summary, Summary: baseCfg.Summary,
Description: baseCfg.Description, Description: baseCfg.Description,
ExternalDocs: nil, ExternalDocs: nil,
OperationID: baseCfg.Summary + "(" + strings.ReplaceAll(strings.TrimLeft(baseCfg.Uri, "/"), "/", "-") + ")", OperationID: baseCfg.Summary + "(" + baseCfg.Method + "-" + strings.ReplaceAll(strings.TrimLeft(baseCfg.Uri, "/"), "/", "-") + ")",
Parameters: make([]*define.PathConfigParameter, 0), Parameters: make([]*define.PathConfigParameter, 0),
RequestBody: &define.RequestBody{ RequestBody: &define.RequestBody{
Required: true, Required: true,
@ -326,7 +326,11 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
baseReqCfg.Parameters = make([]*define.PathConfigParameter, 0) 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)) if inputType.Field(i).Anonymous {
// 匿名字段, 直接对齐到当前的父级
g.ParseReadConfigParam(requestCfg, baseReqCfg, inputType.Field(i).Type)
}
propertyName := ParseStructFieldTag.GetParamName(inputType.Field(i))
if propertyName == "-" { if propertyName == "-" {
continue continue
} }
@ -334,22 +338,43 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
// 空Meta字段认为是用来描述元信息的, 忽略 // 空Meta字段认为是用来描述元信息的, 忽略
continue continue
} }
convertBaseType, isBaseType := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
realInputTypeFormat := inputType.Field(i).Type.String() realInputTypeFormat := inputType.Field(i).Type.String()
fieldType := inputType.Field(i).Type fieldType := inputType.Field(i).Type
/*if inputType.Field(i).Type.Kind() == reflect.Ptr { /*if inputType.Field(i).Type.Kind() == reflect.Ptr {
fieldType = inputType.Field(i).Type.Elem() fieldType = inputType.Field(i).Type.Elem()
}*/ }*/
if isBaseType {
// 当做默认基础类型, 默认不会出现 *map *[]
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
Name: propertyName,
In: consts.SwaggerParameterInQuery,
Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Required: ValidateRule.IsRequired(inputType.Field(i)),
Deprecated: ParseStructFieldTag.Deprecated(inputType.Field(i)),
Schema: &define.Schema{
Type: convertBaseType,
Format: realInputTypeFormat,
},
AllowEmptyValue: false,
Style: "",
Explode: false,
AllowReserved: false,
})
continue
}
if inputType.Field(i).Type.Kind() == reflect.Ptr { if inputType.Field(i).Type.Kind() == reflect.Ptr {
// 处理指针 // 处理指针
if inputType.Field(i).Type.Elem().Kind() == reflect.Struct { if inputType.Field(i).Type.Elem().Kind() == reflect.Struct {
// 结构体指针 // 结构体指针
schemaNameNext := g.AddComponentsSchema("", propertyName, inputType.Field(i).Type.Elem()) schemaNameNext := g.AddComponentsSchema("", propertyName, inputType.Field(i).Type.Elem())
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{ baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
Name: propertyName, Name: propertyName,
In: consts.SwaggerParameterInQuery, In: consts.SwaggerParameterInQuery,
Description: ParseStructField.GetParamDesc(inputType.Field(i)), Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Required: ValidateRule.IsRequired(inputType.Field(i)), Required: ValidateRule.IsRequired(inputType.Field(i)),
Deprecated: ParseStructField.Deprecated(inputType.Field(i)), Deprecated: ParseStructFieldTag.Deprecated(inputType.Field(i)),
Schema: &define.Schema{ Schema: &define.Schema{
// Format: realInputTypeFormat, // Format: realInputTypeFormat,
Ref: g.getSchemaRef(schemaNameNext), Ref: g.getSchemaRef(schemaNameNext),
@ -359,22 +384,7 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
AllowReserved: false, AllowReserved: false,
}) })
} else { } else {
// 当做默认基础类型, 默认不会出现 *map *[]
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
Name: propertyName,
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()),
Format: realInputTypeFormat,
},
AllowEmptyValue: false,
Style: "",
Explode: false,
AllowReserved: false,
})
} }
continue continue
} }
@ -382,37 +392,14 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
fieldType.Kind() == reflect.Map || fieldType.Kind() == reflect.Map ||
fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Array ||
fieldType.Kind() == reflect.Slice { fieldType.Kind() == reflect.Slice {
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
}
} else {
baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{ baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{
Name: ParseStructField.GetParamName(inputType.Field(i)), Name: ParseStructFieldTag.GetParamName(inputType.Field(i)),
In: consts.SwaggerParameterInQuery, In: consts.SwaggerParameterInQuery,
Description: ParseStructField.GetParamDesc(inputType.Field(i)), Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Required: ValidateRule.IsRequired(inputType.Field(i)), Required: ValidateRule.IsRequired(inputType.Field(i)),
Deprecated: ParseStructField.Deprecated(inputType.Field(i)), Deprecated: ParseStructFieldTag.Deprecated(inputType.Field(i)),
Schema: &define.Schema{ Schema: &define.Schema{
Type: g.realBaseType2SwaggerType(inputType.Field(i).Type.String()), Type: convertBaseType,
Items: nil, Items: nil,
Ref: "", Ref: "",
Format: realInputTypeFormat, Format: realInputTypeFormat,
@ -482,16 +469,25 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
} }
// 数组 // 数组
if inputType.Kind() == reflect.Slice || inputType.Kind() == reflect.Array { if inputType.Kind() == reflect.Slice || inputType.Kind() == reflect.Array {
sliceItemType, itemIsBaseType := g.parseSliceItem(schemaName, inputType)
propertyXOf := &define.PropertyXOf{}
if itemIsBaseType {
propertyXOf.Type, _ = g.realBaseType2SwaggerType(sliceItemType)
propertyXOf.Format = sliceItemType
propertyXOf.Ref = ""
} else {
propertyXOf.Type = ""
propertyXOf.Format = ""
propertyXOf.Ref = g.getSchemaRef(sliceItemType)
}
if len(rootSchemaName) == 0 { if len(rootSchemaName) == 0 {
g.docData.Components.Schemas[schemaName].Type = consts.SwaggerDataTypeArray g.docData.Components.Schemas[schemaName].Type = consts.SwaggerDataTypeArray
sliceItemType := g.parseSliceItem(schemaName, inputType) g.docData.Components.Schemas[schemaName].Items = propertyXOf
g.docData.Components.Schemas[schemaName].Items = &define.PropertyXOf{Ref: g.getSchemaRef(sliceItemType)}
} else { } else {
sliceItemType := g.parseSliceItem(schemaName, inputType)
g.docData.Components.Schemas[rootSchemaName].Properties[schemaName] = &define.Property{ g.docData.Components.Schemas[rootSchemaName].Properties[schemaName] = &define.Property{
Type: consts.SwaggerDataTypeArray, Type: consts.SwaggerDataTypeArray,
Format: inputType.String(), Format: inputType.String(),
Items: &define.PropertyXOf{Ref: g.getSchemaRef(sliceItemType)}, Items: propertyXOf,
} }
} }
@ -500,7 +496,12 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
// 结构体 // 结构体
if inputType.Kind() == reflect.Struct { if inputType.Kind() == reflect.Struct {
for i := 0; i < inputType.NumField(); i++ { for i := 0; i < inputType.NumField(); i++ {
propertyName := ParseStructField.GetParamName(inputType.Field(i)) if inputType.Field(i).Anonymous {
// 处理匿名字段
g.handleAnonymousField(schemaName, inputType.Field(i))
continue
}
propertyName := ParseStructFieldTag.GetParamName(inputType.Field(i))
if propertyName == "-" { if propertyName == "-" {
continue continue
} }
@ -514,11 +515,12 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
} }
} else { } else {
// 当做默认基础类型, 默认不会出现 *map *[] // 当做默认基础类型, 默认不会出现 *map *[]
convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{ g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
Type: g.realBaseType2SwaggerType(g.realBaseType2SwaggerType(inputType.Field(i).Type.String())), Type: convertBaseType,
Format: inputType.Field(i).Type.String(), Format: inputType.Field(i).Type.String(),
Default: ParseStructField.GetDefaultValue(inputType.Field(i)), Default: ParseStructFieldTag.GetDefaultValue(inputType.Field(i)),
Description: ParseStructField.GetParamDesc(inputType.Field(i)), Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
} }
} }
continue continue
@ -532,30 +534,38 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &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: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Properties: map[string]*define.Property{}, Properties: map[string]*define.Property{},
} }
} 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 {
sliceItemType, itemIsBaseType := g.parseSliceItem(schemaName, inputType.Field(i).Type)
propertyXOf := &define.PropertyXOf{}
if itemIsBaseType {
propertyXOf.Type, _ = g.realBaseType2SwaggerType(sliceItemType)
propertyXOf.Format = sliceItemType
propertyXOf.Ref = ""
} else {
propertyXOf.Type = ""
propertyXOf.Format = ""
propertyXOf.Ref = g.getSchemaRef(sliceItemType)
}
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &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: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Items: &define.PropertyXOf{ Items: propertyXOf,
Ref: g.getSchemaRef(g.parseSliceItem(schemaName, inputType.Field(i).Type)),
},
Properties: map[string]*define.Property{},
} }
} else { } else {
g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type) g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type)
} }
} else { } else {
convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{ g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
Type: g.realBaseType2SwaggerType(inputType.Field(i).Type.String()), Type: convertBaseType,
Format: inputType.Field(i).Type.String(), Format: inputType.Field(i).Type.String(),
Default: ParseStructField.GetDefaultValue(inputType.Field(i)), Default: ParseStructFieldTag.GetDefaultValue(inputType.Field(i)),
Description: ParseStructField.GetParamDesc(inputType.Field(i)), Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
} }
} }
// 设置参数各种属性 // 设置参数各种属性
@ -569,7 +579,7 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
// 非基础数据类型 // 非基础数据类型
return g.AddComponentsSchema(schemaName, inputType.Elem().String(), inputType.Elem()) return g.AddComponentsSchema(schemaName, inputType.Elem().String(), inputType.Elem())
} else { } else {
convertType := g.realBaseType2SwaggerType(inputType.String()) convertType, _ := g.realBaseType2SwaggerType(inputType.String())
g.docData.Components.Schemas[schemaName].Properties[schemaName] = &define.Property{ g.docData.Components.Schemas[schemaName].Properties[schemaName] = &define.Property{
Type: convertType, Type: convertType,
Format: inputType.String(), Format: inputType.String(),
@ -580,26 +590,73 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
return schemaName return schemaName
} }
// handleAnonymousField 处理匿名字段
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:43 2025/2/17
func (g *Generate) handleAnonymousField(schemaName string, field reflect.StructField) {
if !field.Anonymous {
// 不是匿名字段
return
}
handleType := field.Type
if handleType.Kind() == reflect.Ptr {
handleType = handleType.Elem()
}
for i := 0; i < handleType.NumField(); i++ {
if handleType.Field(i).Anonymous {
// 递归处理多层嵌套匿名字段
g.handleAnonymousField(schemaName, handleType.Field(i))
continue
} else {
itemField := handleType.Field(i)
baseConvertType, isBaseType := g.realBaseType2SwaggerType(itemField.Type.String())
if !isBaseType {
g.AddComponentsSchema(schemaName, itemField.Type.PkgPath(), itemField.Type)
continue
} else {
paramName := ParseStructFieldTag.GetParamName(itemField)
g.docData.Components.Schemas[schemaName].Properties[paramName] = &define.Property{
Type: baseConvertType,
Format: itemField.Type.String(),
Enum: ValidateRule.Enum(itemField),
Default: ParseStructFieldTag.GetDefaultValue(itemField),
Description: ParseStructFieldTag.GetParamDesc(itemField),
}
if ValidateRule.IsRequired(itemField) {
g.docData.Components.Schemas[schemaName].Required = append(g.docData.Components.Schemas[schemaName].Required, paramName)
}
}
}
}
}
// parseSliceItem 解析数组每一项 // parseSliceItem 解析数组每一项
// //
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 21:33 2025/2/8 // Date : 21:33 2025/2/8
func (g *Generate) parseSliceItem(rootSchemaName string, inputType reflect.Type) string { func (g *Generate) parseSliceItem(rootSchemaName string, inputType reflect.Type) (string, bool) {
if inputType.Kind() != reflect.Slice && inputType.Kind() != reflect.Array { if inputType.Kind() != reflect.Slice && inputType.Kind() != reflect.Array {
// 不是数组 // 不是数组
return "" return "", false
} }
sliceValue := reflect.MakeSlice(inputType, 1, 1) sliceValue := reflect.MakeSlice(inputType, 1, 1)
sliceItemType := sliceValue.Index(0).Type() sliceItemType := sliceValue.Index(0).Type()
realSliceItemType := sliceItemType.String()
if sliceItemType.Kind() == reflect.Ptr { if sliceItemType.Kind() == reflect.Ptr {
sliceItemType = sliceItemType.Elem() sliceItemType = sliceItemType.Elem()
} }
_, isBaseType := g.realBaseType2SwaggerType(sliceItemType.String())
if isBaseType {
return realSliceItemType, true
}
g.AddComponentsSchema(rootSchemaName, sliceItemType.PkgPath(), sliceItemType) g.AddComponentsSchema(rootSchemaName, sliceItemType.PkgPath(), sliceItemType)
if len(sliceItemType.PkgPath()) == 0 { if len(sliceItemType.PkgPath()) == 0 {
return sliceItemType.String() return realSliceItemType, false
} }
return sliceItemType.PkgPath() + "." + sliceItemType.Name() return sliceItemType.PkgPath() + "." + sliceItemType.Name(), false
} }
// getSchemaRef 获取引用的类型 // getSchemaRef 获取引用的类型
@ -612,7 +669,11 @@ func (g *Generate) getSchemaRef(schemaName string) string {
return "" return ""
} }
schemaName = strings.ReplaceAll(schemaName, "*", "") // 去除指针类型 * schemaName = strings.ReplaceAll(schemaName, "*", "") // 去除指针类型 *
return "#/components/schemas/" + strings.ReplaceAll(schemaName, "/", ".") convertType, isBaseType := g.realBaseType2SwaggerType(schemaName)
if isBaseType {
return convertType
}
return "#/components/schemas/" + strings.ReplaceAll(convertType, "/", ".")
} }
// realType2SwaggerType golang 真实数据类型转换为golang数据类型 // realType2SwaggerType golang 真实数据类型转换为golang数据类型
@ -620,48 +681,39 @@ func (g *Generate) getSchemaRef(schemaName string) string {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 20:25 2025/2/11 // Date : 20:25 2025/2/11
func (g *Generate) realBaseType2SwaggerType(realType string) string { func (g *Generate) realBaseType2SwaggerType(realType string) (string, bool) {
switch realType { switch realType {
case "bool", "*bool": case "bool", "*bool":
return consts.SwaggerDataTypeBoolean return consts.SwaggerDataTypeBoolean, true
case "string", "*string": case "string", "*string":
return consts.SwaggerDataTypeString return consts.SwaggerDataTypeString, true
case "byte", "*byte": case "byte", "*byte":
return consts.SwaggerDataTypeByte return consts.SwaggerDataTypeByte, true
case "float32", "*float32", "float64", "*float64": case "float32", "*float32", "float64", "*float64":
return consts.SwaggerDataTypeDouble return consts.SwaggerDataTypeDouble, true
case "int", "*int", "uint", "*uint", "int64", "*int64", "uint64", "*uint64": case "int", "*int", "uint", "*uint", "int64", "*int64", "uint64", "*uint64":
return consts.SwaggerDataTypeInteger return consts.SwaggerDataTypeInteger, true
case "int8", "*int8", "uint8", "*uint8", "int16", "*int16", "uint16", "*uint16", "int32", "*int32", "uint32", "*uint32": case "int8", "*int8", "uint8", "*uint8", "int16", "*int16", "uint16", "*uint16", "int32", "*int32", "uint32", "*uint32":
return consts.SwaggerDataTypeInteger return consts.SwaggerDataTypeInteger, true
default: default:
return realType if strings.HasPrefix(realType, "[]") {
return consts.SwaggerDataTypeArray, true
}
return realType, false
} }
} }
// realType2SwaggerType ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:20 2025/2/11
func (g *Generate) realType2SwaggerType(realType string) string {
if strings.HasPrefix(realType, "[]") {
return consts.SwaggerDataTypeArray
}
return g.realBaseType2SwaggerType(realType)
}
// setStructFieldProperty 添加struct_field各种属性 // setStructFieldProperty 添加struct_field各种属性
// //
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 16:13 2025/2/13 // Date : 16:13 2025/2/13
func (g *Generate) setStructFieldProperty(schemaName string, structField reflect.StructField) { func (g *Generate) setStructFieldProperty(schemaName string, structField reflect.StructField) {
paramName := ParseStructField.GetParamName(structField) paramName := ParseStructFieldTag.GetParamName(structField)
if ValidateRule.IsRequired(structField) { if ValidateRule.IsRequired(structField) {
g.docData.Components.Schemas[schemaName].Required = append(g.docData.Components.Schemas[schemaName].Required, paramName) g.docData.Components.Schemas[schemaName].Required = append(g.docData.Components.Schemas[schemaName].Required, paramName)
} }
g.docData.Components.Schemas[schemaName].Properties[ParseStructField.GetParamName(structField)].Enum = ValidateRule.Enum(structField) g.docData.Components.Schemas[schemaName].Properties[ParseStructFieldTag.GetParamName(structField)].Enum = ValidateRule.Enum(structField)
} }
// parseBaseUriConfig 通过Meta字段解析Uri基础配置信息 // parseBaseUriConfig 通过Meta字段解析Uri基础配置信息
@ -718,7 +770,10 @@ func (g *Generate) parseBaseUriConfig(uriPrefix string, paramType reflect.Type)
responseContentType = consts.MimeTypeJson responseContentType = consts.MimeTypeJson
} }
res.OutputContentType = strings.Split(responseContentType, ",") res.OutputContentType = strings.Split(responseContentType, ",")
res.Summary = ParseStructField.Summary(metaField) res.Summary = ParseStructFieldTag.Summary(metaField)
if len(res.Summary) == 0 {
res.Summary = wrapper.String(strings.ReplaceAll(strings.TrimLeft(res.Uri, "/"), "/", "_")).SnakeCaseToCamel()
}
if res.Method == "" { if res.Method == "" {
return nil, errors.New("baseCfg.Method is empty") return nil, errors.New("baseCfg.Method is empty")
} }

View File

@ -25,10 +25,18 @@ type Meta struct {
// //
// 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 UserExt struct {
Job string `json:"job" dc:"job" binding:"required"`
JobPtr *string `json:"job_ptr" dc:"job_ptr" binding:"required"`
Height string `json:"height" dc:"height" binding:"required"`
}
type User struct { type User struct {
Meta `json:"-" deprecated:"false" path:"/user/detail" method:"POST" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"` Meta `json:"-" deprecated:"false" 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"`
IDList []int64 `json:"id_list" dc:"id_list...." binding:"required"`
IDPtrList []*int64 `json:"id_ptr_list" dc:"id_ptr_list...." binding:"required"`
UserExt
} }
type UserDelete struct { type UserDelete struct {
Meta `json:"-" deprecated:"false" path:"/user/detail" method:"DELETE" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"` Meta `json:"-" deprecated:"false" path:"/user/detail" method:"DELETE" desc:"测试接口" tag:"用户,搜索" content_type:"application/json" output_content_type:"application/json"`

View File

@ -15,10 +15,10 @@ import (
) )
var ( var (
ParseStructField = parseStructField{} ParseStructFieldTag = parseStructFieldTag{}
) )
type parseStructField struct { type parseStructFieldTag struct {
} }
// GetParamName 获取参数名称 // GetParamName 获取参数名称
@ -26,7 +26,7 @@ type parseStructField struct {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 21:58 2025/2/11 // Date : 21:58 2025/2/11
func (psf parseStructField) GetParamName(structField reflect.StructField) string { func (psf parseStructFieldTag) GetParamName(structField reflect.StructField) string {
paramNameTagList := []string{ paramNameTagList := []string{
define.TagJson, define.TagForm, define.TagJson, define.TagForm,
define.TagXml, define.TagYaml, define.TagXml, define.TagYaml,
@ -49,7 +49,7 @@ func (psf parseStructField) GetParamName(structField reflect.StructField) string
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 22:01 2025/2/11 // Date : 22:01 2025/2/11
func (psf parseStructField) GetParamDesc(structField reflect.StructField) string { func (psf parseStructFieldTag) GetParamDesc(structField reflect.StructField) string {
descTagList := []string{define.TagDesc, define.TagDescription} descTagList := []string{define.TagDesc, define.TagDescription}
for _, tag := range descTagList { for _, tag := range descTagList {
tagVal := structField.Tag.Get(tag) tagVal := structField.Tag.Get(tag)
@ -66,7 +66,7 @@ func (psf parseStructField) GetParamDesc(structField reflect.StructField) string
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 22:05 2025/2/11 // Date : 22:05 2025/2/11
func (psf parseStructField) GetDefaultValue(structField reflect.StructField) any { func (psf parseStructFieldTag) GetDefaultValue(structField reflect.StructField) any {
defaultTagList := []string{define.TagD, define.TagDefault} defaultTagList := []string{define.TagD, define.TagDefault}
fieldType := structField.Type.Kind().String() fieldType := structField.Type.Kind().String()
for _, tag := range defaultTagList { for _, tag := range defaultTagList {
@ -104,7 +104,7 @@ func (psf parseStructField) GetDefaultValue(structField reflect.StructField) any
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 15:30 2025/2/13 // Date : 15:30 2025/2/13
func (psf parseStructField) GetValidateRule(structField reflect.StructField) string { func (psf parseStructFieldTag) GetValidateRule(structField reflect.StructField) string {
defaultTagList := []string{define.TagValidate, define.TagBinding} defaultTagList := []string{define.TagValidate, define.TagBinding}
for _, tag := range defaultTagList { for _, tag := range defaultTagList {
if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 { if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 {
@ -119,7 +119,7 @@ func (psf parseStructField) GetValidateRule(structField reflect.StructField) str
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 21:12 2025/2/13 // Date : 21:12 2025/2/13
func (psf parseStructField) Deprecated(structField reflect.StructField) bool { func (psf parseStructFieldTag) Deprecated(structField reflect.StructField) bool {
defaultTagList := []string{define.TagDeprecated} defaultTagList := []string{define.TagDeprecated}
for _, tag := range defaultTagList { for _, tag := range defaultTagList {
if tagVal, exist := structField.Tag.Lookup(tag); exist && (tagVal == "1" || strings.ToLower(tagVal) == "true") { if tagVal, exist := structField.Tag.Lookup(tag); exist && (tagVal == "1" || strings.ToLower(tagVal) == "true") {
@ -134,7 +134,7 @@ func (psf parseStructField) Deprecated(structField reflect.StructField) bool {
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 15:15 2025/2/14 // Date : 15:15 2025/2/14
func (psf parseStructField) Summary(structField reflect.StructField) string { func (psf parseStructFieldTag) Summary(structField reflect.StructField) string {
defaultTagList := []string{define.TagSummary} defaultTagList := []string{define.TagSummary}
for _, tag := range defaultTagList { for _, tag := range defaultTagList {
if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 { if tagVal, exist := structField.Tag.Lookup(tag); exist && len(tagVal) > 0 {

View File

@ -85,7 +85,7 @@ func (r validateRule) Enum(structField reflect.StructField) []any {
// Date : 15:29 2025/2/13 // Date : 15:29 2025/2/13
func (r validateRule) getValidateRuleTable(structField reflect.StructField) map[string]string { func (r validateRule) getValidateRuleTable(structField reflect.StructField) map[string]string {
res := map[string]string{} res := map[string]string{}
ruleStr := ParseStructField.GetValidateRule(structField) ruleStr := ParseStructFieldTag.GetValidateRule(structField)
if len(ruleStr) == 0 { if len(ruleStr) == 0 {
return res return res
} }