11Package form
22============
33<img align =" right " src =" https://raw.githubusercontent.com/go-playground/form/master/logo.jpg " >
4- ![ Project status] ( https://img.shields.io/badge/version-1.3 .0-green.svg )
4+ ![ Project status] ( https://img.shields.io/badge/version-1.4 .0-green.svg )
55[ ![ Build Status] ( https://semaphoreci.com/api/v1/joeybloggs/form/branches/master/badge.svg )] ( https://semaphoreci.com/joeybloggs/form )
66[ ![ Coverage Status] ( https://coveralls.io/repos/github/go-playground/form/badge.svg?branch=master )] ( https://coveralls.io/github/go-playground/form?branch=master )
77[ ![ Go Report Card] ( https://goreportcard.com/badge/github.com/go-playground/form )] ( https://goreportcard.com/report/github.com/go-playground/form )
88[ ![ GoDoc] ( https://godoc.org/github.com/go-playground/form?status.svg )] ( https://godoc.org/github.com/go-playground/form )
99![ License] ( https://img.shields.io/dub/l/vibe-d.svg )
1010
11- Package form parses url.Values and fills a struct with values, creating objects as necessary .
11+ Package form Decodes url.Values into struct values and Encodes strut values into url.Values .
1212
1313It has the following features:
1414
7676</form >
7777```
7878
79- Example
79+ Examples
8080-------
81+
82+ Decoding
8183``` go
8284package main
8385
@@ -145,14 +147,82 @@ func parseForm() url.Values {
145147}
146148```
147149
150+ Encoding
151+ ``` go
152+ package main
153+
154+ import (
155+ " fmt"
156+ " log"
157+
158+ " github.com/go-playground/form"
159+ )
160+
161+ // Address contains address information
162+ type Address struct {
163+ Name string
164+ Phone string
165+ }
166+
167+ // User contains user information
168+ type User struct {
169+ Name string
170+ Age uint8
171+ Gender string
172+ Address []Address
173+ Active bool ` form:"active"`
174+ MapExample map [string ]string
175+ NestedMap map [string ]map [string ]string
176+ NestedArray [][]string
177+ }
178+
179+ // use a single instance of Encoder, it caches struct info
180+ var encoder *form.Encoder
181+
182+ func main () {
183+ encoder = form.NewEncoder ()
184+
185+ user := User{
186+ Name: " joeybloggs" ,
187+ Age: 3 ,
188+ Gender: " Male" ,
189+ Address: []Address{
190+ {Name: " 26 Here Blvd." , Phone: " 9(999)999-9999" },
191+ {Name: " 26 There Blvd." , Phone: " 1(111)111-1111" },
192+ },
193+ Active: true ,
194+ MapExample: map [string ]string {" key" : " value" },
195+ NestedMap: map [string ]map [string ]string {" key" : {" key" : " value" }},
196+ NestedArray: [][]string {{" value" }},
197+ }
198+
199+ // must pass a pointer
200+ values , err := encoder.Encode (&user)
201+ if err != nil {
202+ log.Panic (err)
203+ }
204+
205+ fmt.Printf (" %#v \n " , values)
206+ }
207+ ```
208+
148209Registering Custom Types
149210--------------
211+
212+ Decoder
150213``` go
151214decoder.RegisterCustomTypeFunc (func (vals []string ) (interface {}, error ) {
152215 return time.Parse (" 2006-01-02" , vals[0 ])
153216 }, time.Time {})
154217```
155218
219+ Encoder
220+ ``` go
221+ encoder.RegisterCustomTypeFunc (func (x interface {}) ([]string , error ) {
222+ return []string {x.(time.Time ).Format (" 2006-01-02" )}, nil
223+ }, time.Time {})
224+ ```
225+
156226Ignoring Fields
157227--------------
158228you can tell form to ignore fields using ` - ` in the tag
@@ -162,26 +232,62 @@ type MyStruct struct {
162232}
163233```
164234
235+ Notes
236+ ------
237+ To maximize compatibility with other systems the Encoder attempts
238+ to avoid using array indexes in url.Values if at all possible.
239+
240+ eg.
241+ ``` go
242+ // A struct field of
243+ Field []string {" 1" , " 2" , " 3" }
244+
245+ // will be output a url.Value as
246+ " Field" : []string {" 1" , " 2" , " 3" }
247+
248+ and not
249+ " Field[0]" : []string {" 1" }
250+ " Field[1]" : []string {" 2" }
251+ " Field[2]" : []string {" 3" }
252+
253+ // however there are times where it is unavoidable, like with pointers
254+ i := int (1 )
255+ Field []*string {nil , nil , &i}
256+
257+ // to avoid index 1 and 2 must use index
258+ " Field[2]" : []string {" 1" }
259+ ```
260+
165261Benchmarks
166262------
167263###### Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3 using Go version go1.6.2 darwin/amd64
168264
169- NOTE: the 1 allocation and B/op in the first 4 is actually the struct allocating when passing it in, so primitives are actually zero allocation.
265+ NOTE: the 1 allocation and B/op in the first 4 decodes is actually the struct allocating when passing it in, so primitives are actually zero allocation.
170266
171267``` go
172268go test -bench=. -benchmem=true
173269
174270PASS
175- BenchmarkSimpleUserStruct-8 5000000 299 ns/op 64 B /op 1 allocs/op
176- BenchmarkSimpleUserStructParallel-8 20000000 110 ns/op 64 B /op 1 allocs/op
177- BenchmarkPrimitivesStructAllPrimitivesTypes-8 2000000 956 ns/op 96 B /op 1 allocs/op
178- BenchmarkPrimitivesStructAllPrimitivesTypesParallel-8 5000000 285 ns/op 96 B /op 1 allocs/op
179- BenchmarkComplexArrayStructAllTypes-8 100000 20706 ns/op 6776 B /op 159 allocs/op
180- BenchmarkComplexArrayStructAllTypesParallel-8 200000 6158 ns/op 6776 B /op 159 allocs/op
181- BenchmarkComplexMapStructAllTypes-8 50000 35548 ns/op 20966 B /op 245 allocs/op
182- BenchmarkComplexMapStructAllTypesParallel-8 200000 11984 ns/op 20966 B /op 245 allocs/op
183- BenchmarkArrayMapNestedStruct-8 200000 5617 ns/op 2064 B /op 37 allocs/op
184- BenchmarkArrayMapNestedStructParallel-8 1000000 2032 ns/op 2064 B /op 37 allocs/op
271+ BenchmarkSimpleUserDecodeStruct-8 5000000 293 ns/op 64 B /op 1 allocs/op
272+ BenchmarkSimpleUserDecodeStructParallel-8 20000000 112 ns/op 64 B /op 1 allocs/op
273+ BenchmarkSimpleUserEncodeStruct-8 2000000 808 ns/op 466 B /op 7 allocs/op
274+ BenchmarkSimpleUserEncodeStructParallel-8 5000000 278 ns/op 466 B /op 7 allocs/op
275+ BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 2000000 965 ns/op 96 B /op 1 allocs/op
276+ BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 5000000 284 ns/op 96 B /op 1 allocs/op
277+ BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 300000 4349 ns/op 2913 B /op 32 allocs/op
278+ BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1000000 1469 ns/op 2913 B /op 32 allocs/op
279+ BenchmarkComplexArrayDecodeStructAllTypes-8 100000 20608 ns/op 6776 B /op 159 allocs/op
280+ BenchmarkComplexArrayDecodeStructAllTypesParallel-8 200000 6265 ns/op 6776 B /op 159 allocs/op
281+ BenchmarkComplexArrayEncodeStructAllTypes-8 100000 17198 ns/op 7192 B /op 154 allocs/op
282+ BenchmarkComplexArrayEncodeStructAllTypesParallel-8 300000 5157 ns/op 7191 B /op 154 allocs/op
283+ BenchmarkComplexMapDecodeStructAllTypes-8 50000 34637 ns/op 20869 B /op 241 allocs/op
284+ BenchmarkComplexMapDecodeStructAllTypesParallel-8 100000 12095 ns/op 20870 B /op 241 allocs/op
285+ BenchmarkComplexMapEncodeStructAllTypes-8 100000 18193 ns/op 7095 B /op 177 allocs/op
286+ BenchmarkComplexMapEncodeStructAllTypesParallel-8 300000 5651 ns/op 7096 B /op 177 allocs/op
287+ BenchmarkDecodeNestedStruct-8 300000 5537 ns/op 2064 B /op 37 allocs/op
288+ BenchmarkDecodeNestedStructParallel-8 1000000 1932 ns/op 2064 B /op 37 allocs/op
289+ BenchmarkEncodeNestedStruct-8 500000 2956 ns/op 848 B /op 26 allocs/op
290+ BenchmarkEncodeNestedStructParallel-8 1000000 1168 ns/op 848 B /op 26 allocs/op
185291```
186292
187293Competitor benchmarks can be found [ here] ( https://github.com/go-playground/form/blob/master/benchmarks/benchmarks.md )
0 commit comments