summaryrefslogblamecommitdiffstats
path: root/vendor/github.com/gorilla/schema/doc.go
blob: 22c0ff4bf32b813421d0c55c0ec04fbb63d560ec (plain) (tree)


















































































































































                                                                               
// 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 Load() 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