1// Copyright 2012 The Gorilla Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5/* 6Package gorilla/schema fills a struct with form values. 7 8The basic usage is really simple. Given this struct: 9 10 type Person struct { 11 Name string 12 Phone string 13 } 14 15...we can fill it passing a map to the Decode() function: 16 17 values := map[string][]string{ 18 "Name": {"John"}, 19 "Phone": {"999-999-999"}, 20 } 21 person := new(Person) 22 decoder := schema.NewDecoder() 23 decoder.Decode(person, values) 24 25This is just a simple example and it doesn't make a lot of sense to create 26the map manually. Typically it will come from a http.Request object and 27will be of type url.Values, http.Request.Form, or http.Request.MultipartForm: 28 29 func MyHandler(w http.ResponseWriter, r *http.Request) { 30 err := r.ParseForm() 31 32 if err != nil { 33 // Handle error 34 } 35 36 decoder := schema.NewDecoder() 37 // r.PostForm is a map of our POST form values 38 err := decoder.Decode(person, r.PostForm) 39 40 if err != nil { 41 // Handle error 42 } 43 44 // Do something with person.Name or person.Phone 45 } 46 47Note: it is a good idea to set a Decoder instance as a package global, 48because it caches meta-data about structs, and an instance can be shared safely: 49 50 var decoder = schema.NewDecoder() 51 52To define custom names for fields, use a struct tag "schema". To not populate 53certain fields, use a dash for the name and it will be ignored: 54 55 type Person struct { 56 Name string `schema:"name"` // custom name 57 Phone string `schema:"phone"` // custom name 58 Admin bool `schema:"-"` // this field is never set 59 } 60 61The supported field types in the destination struct are: 62 63 * bool 64 * float variants (float32, float64) 65 * int variants (int, int8, int16, int32, int64) 66 * string 67 * uint variants (uint, uint8, uint16, uint32, uint64) 68 * struct 69 * a pointer to one of the above types 70 * a slice or a pointer to a slice of one of the above types 71 72Non-supported types are simply ignored, however custom types can be registered 73to be converted. 74 75To fill nested structs, keys must use a dotted notation as the "path" for the 76field. So for example, to fill the struct Person below: 77 78 type Phone struct { 79 Label string 80 Number string 81 } 82 83 type Person struct { 84 Name string 85 Phone Phone 86 } 87 88...the source map must have the keys "Name", "Phone.Label" and "Phone.Number". 89This means that an HTML form to fill a Person struct must look like this: 90 91 <form> 92 <input type="text" name="Name"> 93 <input type="text" name="Phone.Label"> 94 <input type="text" name="Phone.Number"> 95 </form> 96 97Single values are filled using the first value for a key from the source map. 98Slices are filled using all values for a key from the source map. So to fill 99a Person with multiple Phone values, like: 100 101 type Person struct { 102 Name string 103 Phones []Phone 104 } 105 106...an HTML form that accepts three Phone values would look like this: 107 108 <form> 109 <input type="text" name="Name"> 110 <input type="text" name="Phones.0.Label"> 111 <input type="text" name="Phones.0.Number"> 112 <input type="text" name="Phones.1.Label"> 113 <input type="text" name="Phones.1.Number"> 114 <input type="text" name="Phones.2.Label"> 115 <input type="text" name="Phones.2.Number"> 116 </form> 117 118Notice that only for slices of structs the slice index is required. 119This is needed for disambiguation: if the nested struct also had a slice 120field, we could not translate multiple values to it if we did not use an 121index for the parent struct. 122 123There's also the possibility to create a custom type that implements the 124TextUnmarshaler interface, and in this case there's no need to register 125a converter, like: 126 127 type Person struct { 128 Emails []Email 129 } 130 131 type Email struct { 132 *mail.Address 133 } 134 135 func (e *Email) UnmarshalText(text []byte) (err error) { 136 e.Address, err = mail.ParseAddress(string(text)) 137 return 138 } 139 140...an HTML form that accepts three Email values would look like this: 141 142 <form> 143 <input type="email" name="Emails.0"> 144 <input type="email" name="Emails.1"> 145 <input type="email" name="Emails.2"> 146 </form> 147*/ 148package schema 149