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
This commit is contained in:
田欧 2018-04-25 16:24:03 +08:00 committed by Bo-Yi Wu
parent 814ac9490a
commit 41f951e0cd
2 changed files with 68 additions and 1 deletions

View File

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

View File

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