Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix #3245 #3298

Merged
merged 10 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion database/gdb/gdb_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gmeta"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
)

Expand Down Expand Up @@ -70,7 +71,7 @@ var (
quoteWordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)

// structTagPriority tags for struct converting for orm field mapping.
structTagPriority = append([]string{OrmTagForStruct}, gconv.StructTagPriority...)
structTagPriority = append([]string{OrmTagForStruct}, gtag.StructTagPriority...)
)

// WithDB injects given db object into context and returns a new context.
Expand Down
6 changes: 3 additions & 3 deletions net/ghttp/ghttp_request_param.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import (
)

const (
parseTypeRequest = 0
parseTypeQuery = 1
parseTypeForm = 2
parseTypeRequest = iota
parseTypeQuery
parseTypeForm
)

var (
Expand Down
5 changes: 3 additions & 2 deletions net/ghttp/ghttp_request_param_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func (r *Request) doGetRequestStruct(pointer interface{}, mapping ...map[string]
if err = r.mergeInTagStructValue(data, pointer); err != nil {
return data, nil
}

return data, gconv.Struct(data, pointer, mapping...)
}

Expand Down Expand Up @@ -262,7 +263,7 @@ func (r *Request) mergeInTagStructValue(data map[string]interface{}, pointer int
if tagValue := field.TagIn(); tagValue != "" {
switch tagValue {
case goai.ParameterInHeader:
foundHeaderKey, foundHeaderValue := gutil.MapPossibleItemByKey(headerMap, field.Name())
foundHeaderKey, foundHeaderValue := gutil.MapPossibleItemByKey(headerMap, field.TagPriorityName())
if foundHeaderKey != "" {
foundKey, foundValue = gutil.MapPossibleItemByKey(data, foundHeaderKey)
if foundKey == "" {
Expand All @@ -274,7 +275,7 @@ func (r *Request) mergeInTagStructValue(data map[string]interface{}, pointer int
}
}
case goai.ParameterInCookie:
foundCookieKey, foundCookieValue := gutil.MapPossibleItemByKey(cookieMap, field.Name())
foundCookieKey, foundCookieValue := gutil.MapPossibleItemByKey(cookieMap, field.TagPriorityName())
if foundCookieKey != "" {
foundKey, foundValue = gutil.MapPossibleItemByKey(data, foundCookieKey)
if foundKey == "" {
Expand Down
44 changes: 44 additions & 0 deletions net/ghttp/ghttp_z_unit_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,3 +524,47 @@ func Test_Issue2457(t *testing.T) {
t.Assert(c.GetContent(ctx, "/list"), `{"code":0,"message":"","data":{"Code":100,"Data":{"Title":"title","Content":"hello"},"Msg":""}}`)
})
}

// https://github.com/gogf/gf/issues/3245
type Issue3245Req struct {
g.Meta `path:"/hello" method:"get"`
Name string `p:"nickname" json:"name"`
XHeaderName string `p:"Header-Name" in:"header" json:"X-Header-Name"`
XHeaderAge uint8 `p:"Header-Age" in:"cookie" json:"X-Header-Age"`
}
type Issue3245Res struct {
Reply any
}

type Issue3245V1 struct{}

func (Issue3245V1) Hello(ctx context.Context, req *Issue3245Req) (res *Issue3245Res, err error) {
res = &Issue3245Res{
Reply: req,
}
return
}

func Test_Issue3245(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := g.Server(guid.S())
s.Use(ghttp.MiddlewareHandlerResponse)
s.Group("/", func(group *ghttp.RouterGroup) {
group.Bind(
new(Issue3245V1),
)
})
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()
time.Sleep(100 * time.Millisecond)

c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
c.SetHeader("Header-Name", "oldme")
c.SetCookie("Header-Age", "25")

expect := `{"code":0,"message":"","data":{"Reply":{"name":"oldme","X-Header-Name":"oldme","X-Header-Age":25}}}`
t.Assert(c.GetContent(ctx, "/hello?nickname=oldme"), expect)
})
}
9 changes: 1 addition & 8 deletions net/goai/goai_parameter_ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/os/gstructs"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
)

// Parameters is specified by OpenAPI/Swagger 3.0 standard.
Expand All @@ -30,14 +29,8 @@ type ParameterRef struct {
func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path, method string) (*ParameterRef, error) {
var (
tagMap = field.TagMap()
fieldName = field.Name()
fieldName = field.TagPriorityName()
)
for _, tagName := range gconv.StructTagPriority {
if tagValue := field.Tag(tagName); tagValue != "" {
fieldName = tagValue
break
}
}
fieldName = gstr.Split(gstr.Trim(fieldName), ",")[0]
if fieldName == "" {
fieldName = field.Name()
Expand Down
8 changes: 1 addition & 7 deletions net/goai/goai_shema.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) {
if !gstr.IsLetterUpper(structField.Name()[0]) {
continue
}
var fieldName = structField.Name()
for _, tagName := range gconv.StructTagPriority {
if tagValue := structField.Tag(tagName); tagValue != "" {
fieldName = tagValue
break
}
}
var fieldName = structField.TagPriorityName()
fieldName = gstr.Split(gstr.Trim(fieldName), ",")[0]
if fieldName == "" {
fieldName = structField.Name()
Expand Down
6 changes: 3 additions & 3 deletions os/gstructs/gstructs.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ type FieldMapInput struct {
type RecursiveOption int

const (
RecursiveOptionNone RecursiveOption = 0 // No recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbedded RecursiveOption = 1 // Recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbeddedNoTag RecursiveOption = 2 // Recursively retrieving fields as map if the field is an embedded struct and the field has no tag.
RecursiveOptionNone RecursiveOption = iota // No recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbedded // Recursively retrieving fields as map if the field is an embedded struct.
RecursiveOptionEmbeddedNoTag // Recursively retrieving fields as map if the field is an embedded struct and the field has no tag.
)

// Fields retrieves and returns the fields of `pointer` as slice.
Expand Down
13 changes: 13 additions & 0 deletions os/gstructs/gstructs_field_tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,16 @@ func (f *Field) TagIn() string {
v := f.Tag(gtag.In)
return v
}

// TagPriorityName checks and returns tag name that matches the name item in `gtag.StructTagPriority`.
// It or else returns attribute field Name if it doesn't have a tag name by `gtag.StructsTagPriority`.
func (f *Field) TagPriorityName() string {
var name = f.Name()
for _, tagName := range gtag.StructTagPriority {
if tagValue := f.Tag(tagName); tagValue != "" {
name = tagValue
break
}
}
return name
}
20 changes: 20 additions & 0 deletions os/gstructs/gstructs_z_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,23 @@ func TestType_TagExample(t *testing.T) {
t.Assert(r[1].TagExample(), `john`)
})
}

func Test_Fields_TagPriorityName(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string `gconv:"name_gconv" c:"name_c"`
Age uint `p:"name_p" param:"age_param"`
Pass string `json:"pass_json"`
IsMen bool
}
var user *User
fields, _ := gstructs.Fields(gstructs.FieldsInput{
Pointer: user,
RecursiveOption: 0,
})
t.Assert(fields[0].TagPriorityName(), "name_gconv")
t.Assert(fields[1].TagPriorityName(), "age_param")
t.Assert(fields[2].TagPriorityName(), "pass_json")
t.Assert(fields[3].TagPriorityName(), "IsMen")
})
}
4 changes: 1 addition & 3 deletions util/gconv/gconv.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@ var (
// StructTagPriority defines the default priority tags for Map*/Struct* functions.
// Note that, the `gconv/param` tags are used by old version of package.
// It is strongly recommended using short tag `c/p` instead in the future.
StructTagPriority = []string{
gtag.GConv, gtag.Param, gtag.GConvShort, gtag.ParamShort, gtag.Json,
}
StructTagPriority = gtag.StructTagPriority
)

// Byte converts `any` to byte.
Expand Down
7 changes: 4 additions & 3 deletions util/gconv/gconv_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/utils"
"github.com/gogf/gf/v2/util/gtag"
)

type recursiveType string
Expand Down Expand Up @@ -72,7 +73,7 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool

var (
usedOption = getUsedMapOption(option...)
newTags = StructTagPriority
newTags = gtag.StructTagPriority
)
if usedOption.Deep {
recursive = recursiveTypeTrue
Expand All @@ -81,9 +82,9 @@ func doMapConvert(value interface{}, recursive recursiveType, mustMapReturn bool
case 0:
// No need handling.
case 1:
newTags = append(strings.Split(usedOption.Tags[0], ","), StructTagPriority...)
newTags = append(strings.Split(usedOption.Tags[0], ","), gtag.StructTagPriority...)
default:
newTags = append(usedOption.Tags, StructTagPriority...)
newTags = append(usedOption.Tags, gtag.StructTagPriority...)
}
// Assert the common combination of types, and finally it uses reflection.
dataMap := make(map[string]interface{})
Expand Down
5 changes: 3 additions & 2 deletions util/gconv/gconv_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/utils"
"github.com/gogf/gf/v2/os/gstructs"
"github.com/gogf/gf/v2/util/gtag"
)

// Struct maps the params key-value pairs to the corresponding struct object's attributes.
Expand Down Expand Up @@ -271,9 +272,9 @@ func doStruct(params interface{}, pointer interface{}, paramKeyToAttrMap map[str
priorityTagArray []string
)
if priorityTag != "" {
priorityTagArray = append(utils.SplitAndTrim(priorityTag, ","), StructTagPriority...)
priorityTagArray = append(utils.SplitAndTrim(priorityTag, ","), gtag.StructTagPriority...)
} else {
priorityTagArray = StructTagPriority
priorityTagArray = gtag.StructTagPriority
}
tagToAttrNameMap, err := gstructs.TagMapName(pointerElemReflectValue, priorityTagArray)
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions util/gtag/gtag.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,10 @@ const (
Security = "security" // Security defines scheme for authentication. Detail to see https://swagger.io/docs/specification/authentication/
In = "in" // Swagger distinguishes between the following parameter types based on the parameter location. Detail to see https://swagger.io/docs/specification/describing-parameters/
)

// StructTagPriority defines the default priority tags for Map*/Struct* functions.
// Note that, the `gconv/param` tags are used by old version of package.
// It is strongly recommended using short tag `c/p` instead in the future.
var StructTagPriority = []string{
GConv, Param, GConvShort, ParamShort, Json,
}
Loading