Documentation
¶
Overview ¶
Package urlvalues unmarshals url.Values into struct values.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidStruct = errors.New("urlvalues: target must be a struct pointer")
ErrInvalidStruct indicates that the Unmarshal target is not of correct type.
Functions ¶
func Unmarshal ¶
func Unmarshal(data url.Values, v any, setParseOpts ...SetParseOptionFunc) error
Unmarshal unmarshals data into the value pointed to by v. If v is nil or not a struct pointer, Unmarshal returns an ErrInvalidStruct error.
Slices are decoded by splitting values by a delimiter and parsing each item individually. The delimiter defaults to semicolon (;), but can by customized by passing the WithDelimiter SetParseOptionFunc. Key-value pairs of maps are split using the same delimiter. Keys and their values are separated by a colon (:), with the key to the left and the value to the right of the colon.
Fields with types implementing encoding.TextUnmarshaler and/or encoding.BinaryUnmarshaler will be decoded using those interfaces, respectively. If a type implements both interfaces, the encoding.TextUnmarshaler interface is used to decode the value.
The decoding of each struct field can be customized by the name string stored under the "urlvalue" key in the struct field's tag. The name string acts as a key into data, possibly followed by a comma-separated list of options. The name may be empty, in which case the field name of the struct will act as as key into data in its stead.
The "default" option allows for setting a default value on a field in case corresponding URL value is not present in data, or if the value is the zero value for the field's type.
The "layout" option only applies to fields of type time.Time and allows for customizing how values should be parsed by providing layouts understood by time.Parse. See https://pkg.go.dev/time#pkg-constants for a complete list of the predefined layouts.
As a special case, if the field tag is "-", the field is always omitted. Note that a field with name "-" can still be generated using the tag "-,".
Examples of struct field tags and their meanings:
// Field defaults to 42. Field int `urlvalue:"myName,default:42"` // Field is parsed using the RFC850 layout. Field time.Time `urlvalue:"myName,layout:RFC850"` // Field is ignored by this package. Field int `urlvalue:"-"` // Field appears in URL values with key "-". Field int `urlvalue:"-,"` // Field is decoded as time.Now().AddDate(3, -4, 9). Field time.Time `urlvalue:"myName,default:now+3y-4m+9d"`
The parsing of time.Time is extended to support a "now" based parsing. It parses the value "now" to time.Now. Furthermore, it extends this syntax by allowing the consumer to subtract or add days (d), months (m) and years (y) to "now". This is done by prepending the date identifiers (d,m,y) with a minus (-) or plus (+) sign.
Any error that occurs while processing struct fields results in a FieldError. ParseError wraps around FieldError and is returned if any error occurs while parsing the url.Values that was passed into Unmarshal. ParseError is never returned from errors occuring while parsing default values.
Example ¶
package main import ( "fmt" "net/http" "strings" "time" "github.com/nahojer/urlvalues" ) func main() { req, err := http.NewRequest(http.MethodGet, "http://localhost?since=now-3m&directors=Quentin%20Tarantino&directors=Christopher%20Nolan", nil) if err != nil { panic(err) } var params struct { Since time.Time `urlvalue:"since,default:now-3m,layout:2006-01-02"` Until time.Time `urlvalue:"until,default:now,layout:2006-01-02"` Genres []string `urlvalue:"genres,default:action;drama"` Directors []string `urlvalue:"directors"` NameFilter *string `urlvalue:"name_filter"` OscarNominated *bool `urlvalue:"oscar_nominated,default:false"` } if err := urlvalues.Unmarshal(req.URL.Query(), ¶ms); err != nil { panic(err) } fmt.Printf("Genres: %s\n", strings.Join(params.Genres, ", ")) fmt.Printf("Directors: %s\n", strings.Join(params.Directors, ", ")) fmt.Printf("Name filter: %v\n", params.NameFilter) fmt.Printf("Oscar nominated: %v\n", *params.OscarNominated) }
Output: Genres: action, drama Directors: Quentin Tarantino, Christopher Nolan Name filter: <nil> Oscar nominated: false
Example (ParseError) ¶
package main import ( "errors" "fmt" "net/url" "github.com/nahojer/urlvalues" ) func main() { data := url.Values{"meaning_of_life": {"What do I know?"}} var theBiggestQuestion struct { FortyTwo int `urlvalue:"meaning_of_life"` } if err := urlvalues.Unmarshal(data, &theBiggestQuestion); err != nil { var parseErr *urlvalues.ParseError switch { case errors.As(err, &parseErr): fmt.Println(parseErr) fmt.Printf("Field name: %s\n", parseErr.FieldName) fmt.Printf("Key: %s\n", parseErr.Key) default: panic("never reached") } } }
Output: error parsing value of meaning_of_life: strconv.ParseInt: parsing "What do I know?": invalid syntax Field name: FortyTwo Key: meaning_of_life
Types ¶
type FieldError ¶
type FieldError struct {
// contains filtered or unexported fields
}
FieldError occurs when an error occurs updating an individual field in the provided struct value.
func (*FieldError) Error ¶
func (err *FieldError) Error() string
type ParseError ¶
type ParseError struct { // Name of struct field. FieldName string // Key into URL values. Key string // contains filtered or unexported fields }
ParseError occurs when a url.Values item failed to be parsed into a struct field's type.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
Unwrap returns the underlying FieldError.
type ParseOptions ¶
type ParseOptions struct {
// contains filtered or unexported fields
}
ParseOptions holds all the options that allows for customizing the parsing behaviour when unmarshalling url.Values.
func (*ParseOptions) Delim ¶
func (o *ParseOptions) Delim() string
Delim returns the delimiter used to convert slices and maps from and into their string representation. Defaults to semicolon (;) if not set or set to the empty string.
type SetParseOptionFunc ¶
type SetParseOptionFunc func(*ParseOptions)
SetParseOptionFunc allows for overriding the parsing behaviour of URL values.
func WithDelimiter ¶
func WithDelimiter(s string) SetParseOptionFunc
WithDelimiter returns a SetParseOptionFunc that sets the delimiter used to convert slices and maps from and into their string representation.