// Copyright 2012 The Gorilla Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. /* Package gorilla/schema fills a struct with form values. The basic usage is really simple. Given this struct: type Person struct { Name string Phone string } ...we can fill it passing a map to the Decode() function: values := map[string][]string{ "Name": {"John"}, "Phone": {"999-999-999"}, } person := new(Person) decoder := schema.NewDecoder() decoder.Decode(person, values) This is just a simple example and it doesn't make a lot of sense to create the map manually. Typically it will come from a http.Request object and will be of type url.Values: http.Request.Form or http.Request.MultipartForm: func MyHandler(w http.ResponseWriter, r *http.Request) { err := r.ParseForm() if err != nil { // Handle error } decoder := schema.NewDecoder() // r.PostForm is a map of our POST form values err := decoder.Decode(person, r.PostForm) if err != nil { // Handle error } // Do something with person.Name or person.Phone } Note: it is a good idea to set a Decoder instance as a package global, because it caches meta-data about structs, and a instance can be shared safely: var decoder = schema.NewDecoder() To define custom names for fields, use a struct tag "schema". To not populate certain fields, use a dash for the name and it will be ignored: type Person struct { Name string `schema:"name"` // custom name Phone string `schema:"phone"` // custom name Admin bool `schema:"-"` // this field is never set } The supported field types in the destination struct are: * bool * float variants (float32, float64) * int variants (int, int8, int16, int32, int64) * string * uint variants (uint, uint8, uint16, uint32, uint64) * struct * a pointer to one of the above types * a slice or a pointer to a slice of one of the above types Non-supported types are simply ignored, however custom types can be registered to be converted. To fill nested structs, keys must use a dotted notation as the "path" for the field. So for example, to fill the struct Person below: type Phone struct { Label string Number string } type Person struct { Name string Phone Phone } ...the source map must have the keys "Name", "Phone.Label" and "Phone.Number". This means that an HTML form to fill a Person struct must look like this: <form> <input type="text" name="Name"> <input type="text" name="Phone.Label"> <input type="text" name="Phone.Number"> </form> Single values are filled using the first value for a key from the source map. Slices are filled using all values for a key from the source map. So to fill a Person with multiple Phone values, like: type Person struct { Name string Phones []Phone } ...an HTML form that accepts three Phone values would look like this: <form> <input type="text" name="Name"> <input type="text" name="Phones.0.Label"> <input type="text" name="Phones.0.Number"> <input type="text" name="Phones.1.Label"> <input type="text" name="Phones.1.Number"> <input type="text" name="Phones.2.Label"> <input type="text" name="Phones.2.Number"> </form> Notice that only for slices of structs the slice index is required. This is needed for disambiguation: if the nested struct also had a slice field, we could not translate multiple values to it if we did not use an index for the parent struct. There's also the possibility to create a custom type that implements the TextUnmarshaler interface, and in this case there's no need to registry a converter, like: type Person struct { Emails []Email } type Email struct { *mail.Address } func (e *Email) UnmarshalText(text []byte) (err error) { e.Address, err = mail.ParseAddress(string(text)) return } ...an HTML form that accepts three Email values would look like this: <form> <input type="email" name="Emails.0"> <input type="email" name="Emails.1"> <input type="email" name="Emails.2"> </form> */ package schema