From 8ee9d959a0bcc132fae25ce61881c7effbe5c2f5 Mon Sep 17 00:00:00 2001 From: guonaihong Date: Mon, 13 May 2019 10:17:31 +0800 Subject: [PATCH] Now you can parse the inline lowercase start structure (#1893) * Now you can parse the inline lowercase start structure package main import ( "encoding/json" "fmt" "github.com/gin-gonic/gin" ) type appkey struct { Appkey string `json:"appkey" form:"appkey"` } type Query struct { Page int `json:"page" form:"page"` Size int `json:"size" form:"size"` appkey } func main() { router := gin.Default() router.POST("/login", func(c *gin.Context) { var q2 Query if c.ShouldBindQuery(&q2) == nil { c.JSON(200, &q2) } }) router.Run(":8088") } http client: old: curl -X POST "127.0.0.1:8088/login?appkey=china&page=1&size=10" {"page":1,"size":10,"appkey":""} now: curl -X POST "127.0.0.1:8088/login?appkey=china&page=1&size=10" {"page":1,"size":10,"appkey":"china"} * Modify judgment conditions --- binding/binding_test.go | 39 +++++++++++++++++++++++++++++++++++++++ binding/form_mapping.go | 17 ++++++++++------- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/binding/binding_test.go b/binding/binding_test.go index 73bb7700..6710e42b 100644 --- a/binding/binding_test.go +++ b/binding/binding_test.go @@ -24,6 +24,16 @@ import ( "github.com/ugorji/go/codec" ) +type appkey struct { + Appkey string `json:"appkey" form:"appkey"` +} + +type QueryTest struct { + Page int `json:"page" form:"page"` + Size int `json:"size" form:"size"` + appkey +} + type FooStruct struct { Foo string `msgpack:"foo" json:"foo" form:"foo" xml:"foo" binding:"required"` } @@ -189,6 +199,18 @@ func TestBindingForm2(t *testing.T) { "", "") } +func TestBindingFormEmbeddedStruct(t *testing.T) { + testFormBindingEmbeddedStruct(t, "POST", + "/", "/", + "page=1&size=2&appkey=test-appkey", "bar2=foo") +} + +func TestBindingFormEmbeddedStruct2(t *testing.T) { + testFormBindingEmbeddedStruct(t, "GET", + "/?page=1&size=2&appkey=test-appkey", "/?bar2=foo", + "", "") +} + func TestBindingFormDefaultValue(t *testing.T) { testFormBindingDefaultValue(t, "POST", "/", "/", @@ -688,6 +710,23 @@ func TestUriInnerBinding(t *testing.T) { assert.Equal(t, tag.S.Age, expectedAge) } +func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, badBody string) { + b := Form + assert.Equal(t, "form", b.Name()) + + obj := QueryTest{} + req := requestWithBody(method, path, body) + if method == "POST" { + req.Header.Add("Content-Type", MIMEPOSTForm) + } + err := b.Bind(req, &obj) + assert.NoError(t, err) + assert.Equal(t, 1, obj.Page) + assert.Equal(t, 2, obj.Size) + assert.Equal(t, "test-appkey", obj.Appkey) + +} + func testFormBinding(t *testing.T, method, path, badPath, body, badBody string) { b := Form assert.Equal(t, "form", b.Name()) diff --git a/binding/form_mapping.go b/binding/form_mapping.go index aaacf6c5..32c5b668 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -70,12 +70,14 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag return isSetted, nil } - ok, err := tryToSetValue(value, field, setter, tag) - if err != nil { - return false, err - } - if ok { - return true, nil + if vKind != reflect.Struct || !field.Anonymous { + ok, err := tryToSetValue(value, field, setter, tag) + if err != nil { + return false, err + } + if ok { + return true, nil + } } if vKind == reflect.Struct { @@ -83,7 +85,8 @@ func mapping(value reflect.Value, field reflect.StructField, setter setter, tag var isSetted bool for i := 0; i < value.NumField(); i++ { - if !value.Field(i).CanSet() { + sf := tValue.Field(i) + if sf.PkgPath != "" && !sf.Anonymous { // unexported continue } ok, err := mapping(value.Field(i), tValue.Field(i), setter, tag)