Browse Source

Add support of pointers in form binding (#1336)

* Add support of pointers in form binding

* Add tests for pointer form binding
Alexander Lokhman 7 years ago
parent
commit
2282be059b
2 changed files with 44 additions and 0 deletions
  1. 38 0
      binding/binding_test.go
  2. 6 0
      binding/form_mapping.go

+ 38 - 0
binding/binding_test.go

@@ -144,6 +144,15 @@ type FooBarStructForFloat64Type struct {
 	Float64Bar float64 `form:"float64_bar" binding:"required"`
 	Float64Bar float64 `form:"float64_bar" binding:"required"`
 }
 }
 
 
+type FooStructForStringPtrType struct {
+	PtrFoo *string `form:"ptr_foo"`
+	PtrBar *string `form:"ptr_bar" binding:"required"`
+}
+
+type FooStructForMapPtrType struct {
+	PtrBar *map[string]interface{} `form:"ptr_bar"`
+}
+
 func TestBindingDefault(t *testing.T) {
 func TestBindingDefault(t *testing.T) {
 	assert.Equal(t, Form, Default("GET", ""))
 	assert.Equal(t, Form, Default("GET", ""))
 	assert.Equal(t, Form, Default("GET", MIMEJSON))
 	assert.Equal(t, Form, Default("GET", MIMEJSON))
@@ -378,6 +387,14 @@ func TestBindingFormForType(t *testing.T) {
 	testFormBindingForType(t, "GET",
 	testFormBindingForType(t, "GET",
 		"/?float64_foo=&float64_bar=-12.34", "/?bar2=12.3",
 		"/?float64_foo=&float64_bar=-12.34", "/?bar2=12.3",
 		"", "", "Float64")
 		"", "", "Float64")
+
+	testFormBindingForType(t, "POST",
+		"/", "/",
+		"ptr_bar=test", "bar2=test", "Ptr")
+
+	testFormBindingForType(t, "GET",
+		"/?ptr_bar=test", "/?bar2=test",
+		"", "", "Ptr")
 }
 }
 
 
 func TestBindingQuery(t *testing.T) {
 func TestBindingQuery(t *testing.T) {
@@ -944,6 +961,27 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
 		obj := FooStructForSliceMapType{}
 		obj := FooStructForSliceMapType{}
 		err := b.Bind(req, &obj)
 		err := b.Bind(req, &obj)
 		assert.Error(t, err)
 		assert.Error(t, err)
+	case "Ptr":
+		obj := FooStructForStringPtrType{}
+		err := b.Bind(req, &obj)
+		assert.NoError(t, err)
+		assert.Nil(t, obj.PtrFoo)
+		assert.Equal(t, "test", *obj.PtrBar)
+
+		obj = FooStructForStringPtrType{}
+		obj.PtrBar = new(string)
+		err = b.Bind(req, &obj)
+		assert.NoError(t, err)
+		assert.Equal(t, "test", *obj.PtrBar)
+
+		objErr := FooStructForMapPtrType{}
+		err = b.Bind(req, &objErr)
+		assert.Error(t, err)
+
+		obj = FooStructForStringPtrType{}
+		req = requestWithBody(method, badPath, badBody)
+		err = b.Bind(req, &obj)
+		assert.Error(t, err)
 	}
 	}
 }
 }
 
 

+ 6 - 0
binding/form_mapping.go

@@ -112,6 +112,12 @@ func setWithProperType(valueKind reflect.Kind, val string, structField reflect.V
 		return setFloatField(val, 64, structField)
 		return setFloatField(val, 64, structField)
 	case reflect.String:
 	case reflect.String:
 		structField.SetString(val)
 		structField.SetString(val)
+	case reflect.Ptr:
+		if !structField.Elem().IsValid() {
+			structField.Set(reflect.New(structField.Type().Elem()))
+		}
+		structFieldElem := structField.Elem()
+		return setWithProperType(structFieldElem.Kind(), val, structFieldElem)
 	default:
 	default:
 		return errors.New("Unknown type")
 		return errors.New("Unknown type")
 	}
 	}