Kaynağa Gözat

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
guonaihong 6 yıl önce
ebeveyn
işleme
8ee9d959a0
2 değiştirilmiş dosya ile 49 ekleme ve 7 silme
  1. 39 0
      binding/binding_test.go
  2. 10 7
      binding/form_mapping.go

+ 39 - 0
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())

+ 10 - 7
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)