diff --git a/binding/binding_test.go b/binding/binding_test.go index e29e6dfe..953fb6e8 100644 --- a/binding/binding_test.go +++ b/binding/binding_test.go @@ -74,6 +74,18 @@ type FooStructForSliceType struct { SliceFoo []int `form:"slice_foo"` } +type FooStructForStructType struct { + StructFoo struct { + Idx int `form:"idx"` + } +} + +type FooStructForStructPointerType struct { + StructPointerFoo *struct { + Name string `form:"name"` + } +} + type FooStructForSliceMapType struct { // Unknown type: not support map SliceMapFoo []map[string]interface{} `form:"slice_map_foo"` @@ -395,6 +407,22 @@ func TestBindingFormForType(t *testing.T) { testFormBindingForType(t, "GET", "/?ptr_bar=test", "/?bar2=test", "", "", "Ptr") + + testFormBindingForType(t, "POST", + "/", "/", + "idx=123", "id1=1", "Struct") + + testFormBindingForType(t, "GET", + "/?idx=123", "/?id1=1", + "", "", "Struct") + + testFormBindingForType(t, "POST", + "/", "/", + "name=thinkerou", "name1=ou", "StructPointer") + + testFormBindingForType(t, "GET", + "/?name=thinkerou", "/?name1=ou", + "", "", "StructPointer") } func TestBindingQuery(t *testing.T) { @@ -953,6 +981,20 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s req = requestWithBody(method, badPath, badBody) err = JSON.Bind(req, &obj) assert.Error(t, err) + case "Struct": + obj := FooStructForStructType{} + err := b.Bind(req, &obj) + assert.NoError(t, err) + assert.Equal(t, + struct { Idx int "form:\"idx\"" }(struct { Idx int "form:\"idx\"" }{Idx:123}), + obj.StructFoo) + case "StructPointer": + obj := FooStructForStructPointerType{} + err := b.Bind(req, &obj) + assert.NoError(t, err) + assert.Equal(t, + struct { Name string "form:\"name\"" }(struct { Name string "form:\"name\"" }{Name:"thinkerou"}), + *obj.StructPointerFoo) case "Map": obj := FooStructForMapType{} err := b.Bind(req, &obj) diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 7d5c1022..6ff726df 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -36,9 +36,16 @@ func mapForm(ptr interface{}, form map[string][]string) error { if inputFieldName == "" { inputFieldName = typeField.Name - // if "form" tag is nil, we inspect if the field is a struct. + // if "form" tag is nil, we inspect if the field is a struct or struct pointer. // this would not make sense for JSON parsing but it does for a form // since data is flatten + if structFieldKind == reflect.Ptr { + if !structField.Elem().IsValid() { + structField.Set(reflect.New(structField.Type().Elem())) + } + structField = structField.Elem() + structFieldKind = structField.Kind() + } if structFieldKind == reflect.Struct { err := mapForm(structField.Addr().Interface(), form) if err != nil {