Selaa lähdekoodia

support default value for form (#1138)

* support default value for form

* fix bug for nil interface

* use SplitN and optimization code

* add test case

* add test cases for form(own default value)

* fix invalid code

* fix code indent

* assert order
田欧 7 vuotta sitten
vanhempi
commit
41f951e0cd
2 muutettua tiedostoa jossa 68 lisäystä ja 1 poistoa
  1. 52 0
      binding/binding_test.go
  2. 16 1
      binding/form_mapping.go

+ 52 - 0
binding/binding_test.go

@@ -29,6 +29,11 @@ type FooBarStruct struct {
 	Bar string `msgpack:"bar" json:"bar" form:"bar" xml:"bar" binding:"required"`
 }
 
+type FooDefaultBarStruct struct {
+	FooStruct
+	Bar string `msgpack:"bar" json:"bar" form:"bar,default=hello" xml:"bar" binding:"required"`
+}
+
 type FooStructUseNumber struct {
 	Foo interface{} `json:"foo" binding:"required"`
 }
@@ -195,6 +200,18 @@ func TestBindingForm2(t *testing.T) {
 		"", "")
 }
 
+func TestBindingFormDefaultValue(t *testing.T) {
+	testFormBindingDefaultValue(t, "POST",
+		"/", "/",
+		"foo=bar", "bar2=foo")
+}
+
+func TestBindingFormDefaultValue2(t *testing.T) {
+	testFormBindingDefaultValue(t, "GET",
+		"/?foo=bar", "/?bar2=foo",
+		"", "")
+}
+
 func TestBindingFormForTime(t *testing.T) {
 	testFormBindingForTime(t, "POST",
 		"/", "/",
@@ -407,6 +424,12 @@ func createFormPostRequest() *http.Request {
 	return req
 }
 
+func createDefaultFormPostRequest() *http.Request {
+	req, _ := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
+	req.Header.Set("Content-Type", MIMEPOSTForm)
+	return req
+}
+
 func createFormPostRequestFail() *http.Request {
 	req, _ := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=bar"))
 	req.Header.Set("Content-Type", MIMEPOSTForm)
@@ -450,6 +473,15 @@ func TestBindingFormPost(t *testing.T) {
 	assert.Equal(t, "foo", obj.Bar)
 }
 
+func TestBindingDefaultValueFormPost(t *testing.T) {
+	req := createDefaultFormPostRequest()
+	var obj FooDefaultBarStruct
+	FormPost.Bind(req, &obj)
+
+	assert.Equal(t, "bar", obj.Foo)
+	assert.Equal(t, "hello", obj.Bar)
+}
+
 func TestBindingFormPostFail(t *testing.T) {
 	req := createFormPostRequestFail()
 	var obj FooStructForMapType
@@ -578,6 +610,26 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
 	assert.Error(t, err)
 }
 
+func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badBody string) {
+	b := Form
+	assert.Equal(t, "form", b.Name())
+
+	obj := FooDefaultBarStruct{}
+	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, "bar", obj.Foo)
+	assert.Equal(t, "hello", obj.Bar)
+
+	obj = FooDefaultBarStruct{}
+	req = requestWithBody(method, badPath, badBody)
+	err = JSON.Bind(req, &obj)
+	assert.Error(t, err)
+}
+
 func TestFormBindingFail(t *testing.T) {
 	b := Form
 	assert.Equal(t, "form", b.Name())

+ 16 - 1
binding/form_mapping.go

@@ -8,6 +8,7 @@ import (
 	"errors"
 	"reflect"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -23,6 +24,15 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 
 		structFieldKind := structField.Kind()
 		inputFieldName := typeField.Tag.Get("form")
+		inputFieldNameList := strings.Split(inputFieldName, ",")
+		inputFieldName = inputFieldNameList[0]
+		var defaultValue string
+		if len(inputFieldNameList) > 1 {
+			defaultList := strings.SplitN(inputFieldNameList[1], "=", 2)
+			if defaultList[0] == "default" {
+				defaultValue = defaultList[1]
+			}
+		}
 		if inputFieldName == "" {
 			inputFieldName = typeField.Name
 
@@ -38,8 +48,13 @@ func mapForm(ptr interface{}, form map[string][]string) error {
 			}
 		}
 		inputValue, exists := form[inputFieldName]
+
 		if !exists {
-			continue
+			if defaultValue == "" {
+				continue
+			}
+			inputValue = make([]string, 1)
+			inputValue[0] = defaultValue
 		}
 
 		numElems := len(inputValue)