form – github.com/go-playground/form Index | Files | Directories

package form

import "github.com/go-playground/form"

Package form Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values.

It has the following features:

Common Questions

Questions

Does it support encoding.TextUnmarshaler?
No because TextUnmarshaler only accepts []byte but posted values can have
multiple values, so is not suitable.

Supported Types

out of the box supported types

Usage

symbols

html

<form method="POST">
    <input type="text" name="Name" value="joeybloggs"/>
    <input type="text" name="Age" value="3"/>
    <input type="text" name="Gender" value="Male"/>
    <input type="text" name="Address[0].Name" value="26 Here Blvd."/>
    <input type="text" name="Address[0].Phone" value="9(999)999-9999"/>
    <input type="text" name="Address[1].Name" value="26 There Blvd."/>
    <input type="text" name="Address[1].Phone" value="1(111)111-1111"/>
    <input type="text" name="active" value="true"/>
    <input type="text" name="MapExample[key]" value="value"/>
    <input type="text" name="NestedMap[key][key]" value="value"/>
    <input type="text" name="NestedArray[0][0]" value="value"/>
    <input type="submit"/>
</form>

Example

example decoding the above HTML

package main

import (
    "fmt"
    "log"
    "net/url"

    "github.com/go-playground/form"
)

// Address contains address information
type Address struct {
    Name  string
    Phone string
}

// User contains user information
type User struct {
    Name        string
    Age         uint8
    Gender      string
    Address     []Address
    Active      bool `form:"active"`
    MapExample  map[string]string
    NestedMap   map[string]map[string]string
    NestedArray [][]string
}

// use a single instance of Decoder, it caches struct info
var decoder *form.Decoder

func main() {
    decoder = form.NewDecoder()

    // this simulates the results of http.Request's ParseForm() function
    values := parseForm()

    var user User

    // must pass a pointer
    err := decoder.Decode(&user, values)
    if err != nil {
        log.Panic(err)
    }

    fmt.Printf("%#v\n", user)
}

// this simulates the results of http.Request's ParseForm() function
func parseForm() url.Values {
    return url.Values{
        "Name":                []string{"joeybloggs"},
        "Age":                 []string{"3"},
        "Gender":              []string{"Male"},
        "Address[0].Name":     []string{"26 Here Blvd."},
        "Address[0].Phone":    []string{"9(999)999-9999"},
        "Address[1].Name":     []string{"26 There Blvd."},
        "Address[1].Phone":    []string{"1(111)111-1111"},
        "active":              []string{"true"},
        "MapExample[key]":     []string{"value"},
        "NestedMap[key][key]": []string{"value"},
        "NestedArray[0][0]":   []string{"value"},
    }
}

example encoding

package main

import (
    "fmt"
    "log"

    "github.com/go-playground/form"
)

// Address contains address information
type Address struct {
    Name  string
    Phone string
}

// User contains user information
type User struct {
    Name        string
    Age         uint8
    Gender      string
    Address     []Address
    Active      bool `form:"active"`
    MapExample  map[string]string
    NestedMap   map[string]map[string]string
    NestedArray [][]string
}

// use a single instance of Encoder, it caches struct info
var encoder *form.Encoder

func main() {
    encoder = form.NewEncoder()

    user := User{
        Name:   "joeybloggs",
        Age:    3,
        Gender: "Male",
        Address: []Address{
            {Name: "26 Here Blvd.", Phone: "9(999)999-9999"},
            {Name: "26 There Blvd.", Phone: "1(111)111-1111"},
        },
        Active:      true,
        MapExample:  map[string]string{"key": "value"},
        NestedMap:   map[string]map[string]string{"key": {"key": "value"}},
        NestedArray: [][]string{{"value"}},
    }

    // must pass a pointer
    values, err := encoder.Encode(&user)
    if err != nil {
        log.Panic(err)
    }

    fmt.Printf("%#v\n", values)
}

Registering Custom Types

Decoder

decoder.RegisterCustomTypeFunc(func(vals []string) (interface{}, error) {
        return time.Parse("2006-01-02", vals[0])
    }, time.Time{})

ADDITIONAL: if a struct type is registered, the function will only be called
if a url.Value exists for the struct and not just the struct fields
eg. url.Values{"User":"Name%3Djoeybloggs"} will call the custom type function
with 'User' as the type, however url.Values{"User.Name":"joeybloggs"} will not.

Encoder

encoder.RegisterCustomTypeFunc(func(x interface{}) ([]string, error) {
        return []string{x.(time.Time).Format("2006-01-02")}, nil
    }, time.Time{})

Ignoring Fields

you can tell form to ignore fields using `-` in the tag

type MyStruct struct {
    Field string `form:"-"`
}

Notes

To maximize compatibility with other systems the Encoder attempts to avoid using array indexes in url.Values if at all possible.

eg.

// A struct field of
Field []string{"1", "2", "3"}

// will be output a url.Value as
"Field": []string{"1", "2", "3"}

and not
"Field[0]": []string{"1"}
"Field[1]": []string{"2"}
"Field[2]": []string{"3"}

// however there are times where it is unavoidable, like with pointers
i := int(1)
Field []*string{nil, nil, &i}

// to avoid index 1 and 2 must use index
"Field[2]": []string{"1"}

Index

Functions

func ExtractType

func ExtractType(current reflect.Value) (reflect.Value, reflect.Kind)

ExtractType gets the actual underlying type of field value. it is exposed for use within you Custom Functions

Types

type DecodeCustomTypeFunc

type DecodeCustomTypeFunc func([]string) (interface{}, error)

DecodeCustomTypeFunc allows for registering/overriding types to be parsed.

type DecodeErrors

type DecodeErrors map[string]error

DecodeErrors is a map of errors encountered during form decoding

func (DecodeErrors) Error

func (d DecodeErrors) Error() string

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

Decoder is the main decode instance

func NewDecoder

func NewDecoder() *Decoder

NewDecoder creates a new decoder instance with sane defaults

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{}, values url.Values) (err error)

Decode parses the given values and sets the corresponding struct and/or type values

Decode returns an InvalidDecoderError if interface passed is invalid.

func (*Decoder) RegisterCustomTypeFunc

func (d *Decoder) RegisterCustomTypeFunc(fn DecodeCustomTypeFunc, types ...interface{})

RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types. NOTE: This method is not thread-safe it is intended that these all be registered prior to any parsing

ADDITIONAL: if a struct type is registered, the function will only be called if a url.Value exists for the struct and not just the struct fields eg. url.Values{"User":"Name%3Djoeybloggs"} will call the custom type function with `User` as the type, however url.Values{"User.Name":"joeybloggs"} will not.

func (*Decoder) SetMaxArraySize

func (d *Decoder) SetMaxArraySize(size uint)

SetMaxArraySize sets maximum array size that can be created. This limit is for the array indexing this library supports to avoid potential DOS or man-in-the-middle attacks using an unusually high number. DEFAULT: 10000

func (*Decoder) SetMode

func (d *Decoder) SetMode(mode Mode)

SetMode sets the mode the decoder should run Default is ModeImplicit

func (*Decoder) SetTagName

func (d *Decoder) SetTagName(tagName string)

SetTagName sets the given tag name to be used by the decoder. Default is "form"

type EncodeCustomTypeFunc

type EncodeCustomTypeFunc func(x interface{}) ([]string, error)

EncodeCustomTypeFunc allows for registering/overriding types to be parsed.

type EncodeErrors

type EncodeErrors map[string]error

EncodeErrors is a map of errors encountered during form encoding

func (EncodeErrors) Error

func (e EncodeErrors) Error() string

type Encoder

type Encoder struct {
	// contains filtered or unexported fields
}

Encoder is the main encode instance

func NewEncoder

func NewEncoder() *Encoder

NewEncoder creates a new encoder instance with sane defaults

func (*Encoder) Encode

func (e *Encoder) Encode(v interface{}) (values url.Values, err error)

Encode encodes the given values and sets the corresponding struct values

func (*Encoder) RegisterCustomTypeFunc

func (e *Encoder) RegisterCustomTypeFunc(fn EncodeCustomTypeFunc, types ...interface{})

RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types NOTE: this method is not thread-safe it is intended that these all be registered prior to any parsing

func (*Encoder) SetMode

func (e *Encoder) SetMode(mode Mode)

SetMode sets the mode the encoder should run Default is ModeImplicit

func (*Encoder) SetTagName

func (e *Encoder) SetTagName(tagName string)

SetTagName sets the given tag name to be used by the encoder. Default is "form"

type InvalidDecoderError

type InvalidDecoderError struct {
	Type reflect.Type
}

An InvalidDecoderError describes an invalid argument passed to Decode. (The argument passed to Decode must be a non-nil pointer.)

func (*InvalidDecoderError) Error

func (e *InvalidDecoderError) Error() string

type InvalidEncodeError

type InvalidEncodeError struct {
	Type reflect.Type
}

An InvalidEncodeError describes an invalid argument passed to Encode.

func (*InvalidEncodeError) Error

func (e *InvalidEncodeError) Error() string

type Mode

type Mode uint8

Mode specifies which mode the form decoder is to run

const (

	// ModeImplicit tries to parse values for all
	// fields that do not have an ignore '-' tag
	ModeImplicit Mode = iota

	// ModeExplicit only parses values for field with a field tag
	// and that tag is not the ignore '-' tag
	ModeExplicit
)

Source Files

cache.go decoder.go doc.go encoder.go form.go form_decoder.go form_encoder.go util.go

Directories

PathSynopsis
benchmarks
examples
examples/decoder
examples/encoder
Version
v2.2.1+incompatible
Published
Feb 13, 2017
Platform
js/wasm
Imports
10 packages
Last checked
now

Tools for package owners.