feat(form): Support default values for collections in form binding (#4048)
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				CodeQL / Analyze (go) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / lint (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
				
			
		
			
				
	
				Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	CodeQL / Analyze (go) (push) Has been cancelled
				
			Run Tests / lint (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.21, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, ) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -race) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags "sonic avx") (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags go_json) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/.cache/go-build, ubuntu-latest, -tags nomsgpack) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, ) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -race) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags "sonic avx") (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags go_json) (push) Has been cancelled
				
			Run Tests / ${{ matrix.os }} @ Go ${{ matrix.go }} ${{ matrix.test-tags }} (1.22, ~/Library/Caches/go-build, macos-latest, -tags nomsgpack) (push) Has been cancelled
				
			This commit is contained in:
		@ -159,6 +159,14 @@ func tryToSetValue(value reflect.Value, field reflect.StructField, setter setter
 | 
				
			|||||||
		if k, v := head(opt, "="); k == "default" {
 | 
							if k, v := head(opt, "="); k == "default" {
 | 
				
			||||||
			setOpt.isDefaultExists = true
 | 
								setOpt.isDefaultExists = true
 | 
				
			||||||
			setOpt.defaultValue = v
 | 
								setOpt.defaultValue = v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// convert semicolon-separated default values to csv-separated values for processing in setByForm
 | 
				
			||||||
 | 
								if field.Type.Kind() == reflect.Slice || field.Type.Kind() == reflect.Array {
 | 
				
			||||||
 | 
									cfTag := field.Tag.Get("collection_format")
 | 
				
			||||||
 | 
									if cfTag == "" || cfTag == "multi" || cfTag == "csv" {
 | 
				
			||||||
 | 
										setOpt.defaultValue = strings.ReplaceAll(v, ";", ",")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -224,6 +232,12 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][
 | 
				
			|||||||
	case reflect.Slice:
 | 
						case reflect.Slice:
 | 
				
			||||||
		if !ok {
 | 
							if !ok {
 | 
				
			||||||
			vs = []string{opt.defaultValue}
 | 
								vs = []string{opt.defaultValue}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// pre-process the default value for multi if present
 | 
				
			||||||
 | 
								cfTag := field.Tag.Get("collection_format")
 | 
				
			||||||
 | 
								if cfTag == "" || cfTag == "multi" {
 | 
				
			||||||
 | 
									vs = strings.Split(opt.defaultValue, ",")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ok, err = trySetCustom(vs[0], value); ok {
 | 
							if ok, err = trySetCustom(vs[0], value); ok {
 | 
				
			||||||
@ -238,6 +252,12 @@ func setByForm(value reflect.Value, field reflect.StructField, form map[string][
 | 
				
			|||||||
	case reflect.Array:
 | 
						case reflect.Array:
 | 
				
			||||||
		if !ok {
 | 
							if !ok {
 | 
				
			||||||
			vs = []string{opt.defaultValue}
 | 
								vs = []string{opt.defaultValue}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// pre-process the default value for multi if present
 | 
				
			||||||
 | 
								cfTag := field.Tag.Get("collection_format")
 | 
				
			||||||
 | 
								if cfTag == "" || cfTag == "multi" {
 | 
				
			||||||
 | 
									vs = strings.Split(opt.defaultValue, ",")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ok, err = trySetCustom(vs[0], value); ok {
 | 
							if ok, err = trySetCustom(vs[0], value); ok {
 | 
				
			||||||
 | 
				
			|||||||
@ -323,6 +323,72 @@ func TestMappingCollectionFormat(t *testing.T) {
 | 
				
			|||||||
	assert.Equal(t, [2]int{1, 2}, s.ArrayPipes)
 | 
						assert.Equal(t, [2]int{1, 2}, s.ArrayPipes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMappingCollectionFormatInvalid(t *testing.T) {
 | 
				
			||||||
 | 
						var s struct {
 | 
				
			||||||
 | 
							SliceCsv []int `form:"slice_csv" collection_format:"xxx"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := mappingByPtr(&s, formSource{
 | 
				
			||||||
 | 
							"slice_csv": {"1,2"},
 | 
				
			||||||
 | 
						}, "form")
 | 
				
			||||||
 | 
						require.Error(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var s2 struct {
 | 
				
			||||||
 | 
							ArrayCsv [2]int `form:"array_csv" collection_format:"xxx"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = mappingByPtr(&s2, formSource{
 | 
				
			||||||
 | 
							"array_csv": {"1,2"},
 | 
				
			||||||
 | 
						}, "form")
 | 
				
			||||||
 | 
						require.Error(t, err)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMappingMultipleDefaultWithCollectionFormat(t *testing.T) {
 | 
				
			||||||
 | 
						var s struct {
 | 
				
			||||||
 | 
							SliceMulti       []int     `form:",default=1;2;3" collection_format:"multi"`
 | 
				
			||||||
 | 
							SliceCsv         []int     `form:",default=1;2;3" collection_format:"csv"`
 | 
				
			||||||
 | 
							SliceSsv         []int     `form:",default=1 2 3" collection_format:"ssv"`
 | 
				
			||||||
 | 
							SliceTsv         []int     `form:",default=1\t2\t3" collection_format:"tsv"`
 | 
				
			||||||
 | 
							SlicePipes       []int     `form:",default=1|2|3" collection_format:"pipes"`
 | 
				
			||||||
 | 
							ArrayMulti       [2]int    `form:",default=1;2" collection_format:"multi"`
 | 
				
			||||||
 | 
							ArrayCsv         [2]int    `form:",default=1;2" collection_format:"csv"`
 | 
				
			||||||
 | 
							ArraySsv         [2]int    `form:",default=1 2" collection_format:"ssv"`
 | 
				
			||||||
 | 
							ArrayTsv         [2]int    `form:",default=1\t2" collection_format:"tsv"`
 | 
				
			||||||
 | 
							ArrayPipes       [2]int    `form:",default=1|2" collection_format:"pipes"`
 | 
				
			||||||
 | 
							SliceStringMulti []string  `form:",default=1;2;3" collection_format:"multi"`
 | 
				
			||||||
 | 
							SliceStringCsv   []string  `form:",default=1;2;3" collection_format:"csv"`
 | 
				
			||||||
 | 
							SliceStringSsv   []string  `form:",default=1 2 3" collection_format:"ssv"`
 | 
				
			||||||
 | 
							SliceStringTsv   []string  `form:",default=1\t2\t3" collection_format:"tsv"`
 | 
				
			||||||
 | 
							SliceStringPipes []string  `form:",default=1|2|3" collection_format:"pipes"`
 | 
				
			||||||
 | 
							ArrayStringMulti [2]string `form:",default=1;2" collection_format:"multi"`
 | 
				
			||||||
 | 
							ArrayStringCsv   [2]string `form:",default=1;2" collection_format:"csv"`
 | 
				
			||||||
 | 
							ArrayStringSsv   [2]string `form:",default=1 2" collection_format:"ssv"`
 | 
				
			||||||
 | 
							ArrayStringTsv   [2]string `form:",default=1\t2" collection_format:"tsv"`
 | 
				
			||||||
 | 
							ArrayStringPipes [2]string `form:",default=1|2" collection_format:"pipes"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := mappingByPtr(&s, formSource{}, "form")
 | 
				
			||||||
 | 
						require.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert.Equal(t, []int{1, 2, 3}, s.SliceMulti)
 | 
				
			||||||
 | 
						assert.Equal(t, []int{1, 2, 3}, s.SliceCsv)
 | 
				
			||||||
 | 
						assert.Equal(t, []int{1, 2, 3}, s.SliceSsv)
 | 
				
			||||||
 | 
						assert.Equal(t, []int{1, 2, 3}, s.SliceTsv)
 | 
				
			||||||
 | 
						assert.Equal(t, []int{1, 2, 3}, s.SlicePipes)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]int{1, 2}, s.ArrayMulti)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]int{1, 2}, s.ArrayCsv)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]int{1, 2}, s.ArraySsv)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]int{1, 2}, s.ArrayTsv)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]int{1, 2}, s.ArrayPipes)
 | 
				
			||||||
 | 
						assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringMulti)
 | 
				
			||||||
 | 
						assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringCsv)
 | 
				
			||||||
 | 
						assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringSsv)
 | 
				
			||||||
 | 
						assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringTsv)
 | 
				
			||||||
 | 
						assert.Equal(t, []string{"1", "2", "3"}, s.SliceStringPipes)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringMulti)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringCsv)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringSsv)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringTsv)
 | 
				
			||||||
 | 
						assert.Equal(t, [2]string{"1", "2"}, s.ArrayStringPipes)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestMappingStructField(t *testing.T) {
 | 
					func TestMappingStructField(t *testing.T) {
 | 
				
			||||||
	var s struct {
 | 
						var s struct {
 | 
				
			||||||
		J struct {
 | 
							J struct {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										48
									
								
								docs/doc.md
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								docs/doc.md
									
									
									
									
									
								
							@ -26,6 +26,7 @@
 | 
				
			|||||||
  - [Custom Validators](#custom-validators)
 | 
					  - [Custom Validators](#custom-validators)
 | 
				
			||||||
  - [Only Bind Query String](#only-bind-query-string)
 | 
					  - [Only Bind Query String](#only-bind-query-string)
 | 
				
			||||||
  - [Bind Query String or Post Data](#bind-query-string-or-post-data)
 | 
					  - [Bind Query String or Post Data](#bind-query-string-or-post-data)
 | 
				
			||||||
 | 
					  - [Bind default value if none provided](#bind-default-value-if-none-provided)
 | 
				
			||||||
  - [Collection format for arrays](#collection-format-for-arrays)
 | 
					  - [Collection format for arrays](#collection-format-for-arrays)
 | 
				
			||||||
  - [Bind Uri](#bind-uri)
 | 
					  - [Bind Uri](#bind-uri)
 | 
				
			||||||
  - [Bind custom unmarshaler](#bind-custom-unmarshaler)
 | 
					  - [Bind custom unmarshaler](#bind-custom-unmarshaler)
 | 
				
			||||||
@ -862,6 +863,53 @@ Test it with:
 | 
				
			|||||||
curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033"
 | 
					curl -X GET "localhost:8085/testing?name=appleboy&address=xyz&birthday=1992-03-15&createTime=1562400033000000123&unixTime=1562400033"
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Bind default value if none provided
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the server should bind a default value to a field when the client does not provide one, specify the default value using the `default` key within the `form` tag:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Person struct {
 | 
				
			||||||
 | 
						Name      string    `form:"name,default=William"`
 | 
				
			||||||
 | 
						Age       int       `form:"age,default=10"`
 | 
				
			||||||
 | 
						Friends   []string  `form:"friends,default=Will;Bill"`
 | 
				
			||||||
 | 
						Addresses [2]string `form:"addresses,default=foo bar" collection_format:"ssv"`
 | 
				
			||||||
 | 
						LapTimes  []int     `form:"lap_times,default=1;2;3" collection_format:"csv"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						g := gin.Default()
 | 
				
			||||||
 | 
						g.POST("/person", func(c *gin.Context) {
 | 
				
			||||||
 | 
							var req Person
 | 
				
			||||||
 | 
							if err := c.ShouldBindQuery(&req); err != nil {
 | 
				
			||||||
 | 
								c.JSON(http.StatusBadRequest, err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.JSON(http.StatusOK, req)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						_ = g.Run("localhost:8080")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					curl -X POST http://localhost:8080/person
 | 
				
			||||||
 | 
					{"Name":"William","Age":10,"Friends":["Will","Bill"],"Colors":["red","blue"],"LapTimes":[1,2,3]}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NOTE: For default [collection values](#collection-format-for-arrays), the following rules apply:
 | 
				
			||||||
 | 
					- Since commas are used to delimit tag options, they are not supported within a default value and will result in undefined behavior
 | 
				
			||||||
 | 
					- For the collection formats "multi" and "csv", a semicolon should be used in place of a comma to delimited default values
 | 
				
			||||||
 | 
					- Since semicolons are used to delimit default values for "multi" and "csv", they are not supported within a default value for "multi" and "csv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Collection format for arrays
 | 
					#### Collection format for arrays
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Format          | Description                                               | Example                 |
 | 
					| Format          | Description                                               | Example                 |
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user