diff --git a/README.md b/README.md index 38c67487..8af0cd22 100644 --- a/README.md +++ b/README.md @@ -922,6 +922,53 @@ Test it with: $ curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033" ``` +### Bind Query String or Post Data and assign default value(s) + +```go +package main + +import ( + "log" + "time" + + "github.com/gin-gonic/gin" +) + +type Workplace struct { + Employee string `form:"employee"` + Location string `form:"address,default=headquarter"` + Peripherals []string `form:"peripherals,mutliple_default,default=monitor,mouse,keyboard` + +} + +func main() { + route := gin.Default() + route.GET("/testing", startPage) + route.Run(":8085") +} + +func startPage(c *gin.Context) { + var workplace Workplace + // If `GET`, only `Form` binding engine (`query`) used. + // If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`). + // See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48 + // If default value defined, and the Request does not contain the key, the default value will be used. Empty value from request overrides that behaviour + // If mutliple_default is in front of default, the 'default' value is returned as a slice, the position of mutliple_default is important + if c.ShouldBind(&workplace) == nil { + log.Println(workplace.Employee) + log.Println(workplace.Location) + log.Println(workplace.Peripherals) + } + + c.String(200, "Success") +} +``` + +Test it with: +```sh +$ curl -X GET "localhost:8085/testing?employee=andre" +``` + ### Bind Uri See the [detail information](https://github.com/gin-gonic/gin/issues/846). diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 2f4e45b4..458a09fe 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -142,6 +142,12 @@ func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter var opt string for len(opts) > 0 { opt, opts = head(opts, ",") + if k, _ := head(opt, "="); k == "mutliple_default" { + _, values := head(opts, "=") + setOpt.isDefaultExists = true + setOpt.defaultValue = values + break + } if k, v := head(opt, "="); k == "default" { setOpt.isDefaultExists = true @@ -161,12 +167,12 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][ switch value.Kind() { case reflect.Slice: if !ok { - vs = []string{opt.defaultValue} + vs = strings.Split(opt.defaultValue, ",") } return true, setSlice(vs, value, field) case reflect.Array: if !ok { - vs = []string{opt.defaultValue} + vs = strings.Split(opt.defaultValue, ",") } if len(vs) != value.Len() { return false, fmt.Errorf("%q is not valid value for %s", vs, value.Type().String()) diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index 2675d46b..27cd651c 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -74,6 +74,20 @@ func TestMappingDefault(t *testing.T) { assert.Equal(t, [1]int{9}, s.Array) } +func TestMappingMultipleDefault(t *testing.T) { + var s struct { + Int int `form:",mutliple_default,default=9"` + Slice []int `form:",mutliple_default,default=9"` + Array [1]int `form:",mutliple_default,default=9"` + } + err := mappingByPtr(&s, formSource{}, "form") + assert.NoError(t, err) + + assert.Equal(t, 9, s.Int) + assert.Equal(t, []int{9}, s.Slice) + assert.Equal(t, [1]int{9}, s.Array) +} + func TestMappingSkipField(t *testing.T) { var s struct { A int