1
0
mirror of https://github.com/labstack/echo.git synced 2024-12-24 20:14:31 +02:00

Fix #1858: Add query params binding support for anonymous struct pointer filed

This commit is contained in:
lipengwei 2021-04-25 09:50:14 +08:00 committed by Martti T
parent 2943a32005
commit 18d7fe11df
2 changed files with 54 additions and 0 deletions

View File

@ -144,11 +144,20 @@ func (b *DefaultBinder) bindData(destination interface{}, data map[string][]stri
for i := 0; i < typ.NumField(); i++ {
typeField := typ.Field(i)
structField := val.Field(i)
if typeField.Anonymous {
for structField.Kind() == reflect.Ptr {
structField = structField.Elem()
}
}
if !structField.CanSet() {
continue
}
structFieldKind := structField.Kind()
inputFieldName := typeField.Tag.Get(tag)
if typeField.Anonymous && structField.Kind() == reflect.Struct && inputFieldName != "" {
// if anonymous struct, ignore custom tag
inputFieldName = ""
}
if inputFieldName == "" {
// If tag is nil, we inspect if the field is a not BindUnmarshaler struct and try to bind data into it (might contains fields with tags).

View File

@ -100,6 +100,9 @@ type (
Struct struct {
Foo string
}
Bar struct {
Baz int `json:"baz" query:"baz"`
}
)
func (t *Timestamp) UnmarshalParam(src string) error {
@ -330,6 +333,48 @@ func TestBindUnmarshalParamPtr(t *testing.T) {
}
}
func TestBindUnmarshalParamAnonymousFieldPtr(t *testing.T) {
e := New()
req := httptest.NewRequest(http.MethodGet, "/?baz=1", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
result := struct {
*Bar
}{&Bar{}}
err := c.Bind(&result)
if assert.NoError(t, err) {
assert.Equal(t, 1, result.Baz)
}
}
func TestBindUnmarshalParamAnonymousFieldPtrNil(t *testing.T) {
e := New()
req := httptest.NewRequest(http.MethodGet, "/?baz=1", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
result := struct {
*Bar
}{}
err := c.Bind(&result)
if assert.NoError(t, err) {
assert.Nil(t, result.Bar)
}
}
func TestBindUnmarshalParamAnonymousFieldPtrCustomTag(t *testing.T) {
e := New()
req := httptest.NewRequest(http.MethodGet, `/?bar={"baz":100}&baz=1`, nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
result := struct {
*Bar `json:"bar" query:"bar"`
}{&Bar{}}
err := c.Bind(&result)
if assert.NoError(t, err) {
assert.Equal(t, 1, result.Baz)
}
}
func TestBindUnmarshalTextPtr(t *testing.T) {
e := New()
req := httptest.NewRequest(GET, "/?ts=2016-12-06T19:09:05Z", nil)