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