github.com/pubgo/xprocess@v0.1.11/xprocess_schema/doc.go (about) 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 /* 6 Package gorilla/schema fills a struct with form values. 7 8 The 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 25 This is just a simple example and it doesn't make a lot of sense to create 26 the map manually. Typically it will come from a http.Request object and 27 will 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 47 Note: it is a good idea to set a Decoder instance as a package global, 48 because it caches meta-data about structs, and an instance can be shared safely: 49 50 var decoder = schema.NewDecoder() 51 52 To define custom names for fields, use a struct tag "schema". To not populate 53 certain 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 61 The 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 72 Non-supported types are simply ignored, however custom types can be registered 73 to be converted. 74 75 To fill nested structs, keys must use a dotted notation as the "path" for the 76 field. 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". 89 This 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 97 Single values are filled using the first value for a key from the source map. 98 Slices are filled using all values for a key from the source map. So to fill 99 a 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 118 Notice that only for slices of structs the slice index is required. 119 This is needed for disambiguation: if the nested struct also had a slice 120 field, we could not translate multiple values to it if we did not use an 121 index for the parent struct. 122 123 There's also the possibility to create a custom type that implements the 124 TextUnmarshaler interface, and in this case there's no need to register 125 a 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 */ 148 package xprocess_schema