qs

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 25, 2024 License: MIT Imports: 10 Imported by: 0

README

qs build-status godoc

The qs package can marshal and unmarshal structs into/from url query strings. The interface of qs is very similar to that of some standard marshaler packages like encoding/json, encoding/xml.

Note that html forms are often POST-ed in the HTTP request body in the same format as query strings (with an encoding called application/x-www-form-urlencoded) so this package can be used for that as well.

Quick Intro

The go standard library can convert only between the (query) string and the standard url.Values data type (which is a map[string][]string). This qs package adds struct marshaling and unmarshaling to your arsenal:

                  +--------------+
+---------------->| query string +------------------+
|                 +---------+----+                  |
|                      ^    |                       |
|    url.Values.Encode |    | url.ParseQuery        |
|                      |    v                       |
|                 +----+---------+                  |
|                 |  url.Values  |                  |
|                 +---------+----+                  |
|                      ^    |                       |
|     qs.MarshalValues |    | qs.UnmarshalValues    |
|                      |    v                       |
|                 +----+---------+                  |
+-----------------+    struct    |<-----------------+
    qs.Marshal    +--------------+    qs.Unmarshal

Example:

package main

import "fmt"
import "github.com/pasztorpisti/qs"

type Query struct {
	Search     string
	Page       int
	PageSize   int
	Categories []string `qs:"category"`
}

func main() {
	queryStr, err := qs.Marshal(&Query{
		Search:     "my search",
		Page:       2,
		PageSize:   50,
		Categories: []string{"c1", "c2"},
	})
	fmt.Println("Marshal-Result:", queryStr, err)

	var q Query
	err = qs.Unmarshal(&q, queryStr)
	fmt.Println("Unmarshal-Result:", q, err)

	// Output:
	// Marshal-Result: category=c1&category=c2&page=2&page_size=50&search=my+search <nil>
	// Unmarshal-Result: {my search 2 50 [c1 c2]} <nil>
}

Features

  • Support for primitive types (bool, int, etc...), pointers, slices, arrays, maps, structs, time.Time and url.URL.
  • A custom type can implement the MarshalQS and/or UnmarshalQS interfaces to handle its own marshaling/unmarshaling.
  • The marshaler and unmarshaler are modular and can be extended to support new types. This makes it possible to do several tricks. One of them is being able to override existing type marshalers (e.g.: the []byte array marshaler).
  • It can tell whether a type is marshallable before actually marshaling an object of that type. Most marshalers (including the standard encoding/json) can't do this! E.g.: If you have an empty slice that has a non-marshallable item type (e.g.: function) then encoding/json and many other marshalers happily marshal it as an empty slice - they return with an error only if the given slice has at least one item and they realise that it can't be marshaled.
  • You can create custom marshaler objects that define different defaults for the marshaling process:
    • A struct-to-query_string name transformer func that is used when the struct field tag doesn't set a custom name for the field. The default function converts CamelCase go struct field names to snake_case which is the standard in case of query strings.
    • When a struct field tag specifies none of the keepempty and omitempty options the marshaler uses keepempty by default. By creating a custom marshaler you can change the default to omitempty.
    • When a struct field tag doesn't specify any of the opt, nil, req options the unmarshaler uses opt by default. By creating a custom unmarshaler you can change this default.
  • A struct field tag can be used to:
    • Exclude a field from marshaling/unmarshaling by specifying - as the field name (qs:"-").
    • Set custom name for the field in the marshaled query string.
    • Set one of the keepempty, omitempty options for marshaling.
    • Set one of the opt, nil, req options for unmarshaling.

Detailed Documentation

The godoc of the qs package contains more detailed documentation with working examples.

Documentation

Overview

The qs package can convert structs into query strings and vice versa. The interface of qs is very similar to that of some standard marshaler packages like "encoding/json", "encoding/xml".

Note that html forms are often POST-ed in the HTTP request body in the same format as query strings (which is an encoding called application/x-www-form-urlencoded) so this package can be used for that as well.

Example

This example demonstrates the usage of qs.Marshal and qs.Unmarshal.

package main

import (
	"fmt"

	"github.com/pamburus/qs"
)

type Query struct {
	Search     string
	Page       int
	PageSize   int
	Categories []string `qs:"category"`
}

// This example demonstrates the usage of qs.Marshal and qs.Unmarshal.
func main() {
	queryStr, err := qs.Marshal(&Query{
		Search:     "my search",
		Page:       2,
		PageSize:   50,
		Categories: []string{"c1", "c2"},
	})
	fmt.Println("Marshal-Result:", queryStr, err)

	var q Query
	err = qs.Unmarshal(&q, queryStr)
	fmt.Println("Unmarshal-Result:", q, err)

}
Output:

Marshal-Result: category=c1&category=c2&page=2&page_size=50&search=my+search <nil>
Unmarshal-Result: {my search 2 50 [c1 c2]} <nil>
Example (CustomMarshalerFactory)

This example shows how to create QSMarshaler and QSUnmarshaler objects that have custom marshaler and unmarshaler factories to provide custom marshaling and unmarshaling for some types.

In this example we change the default marshaling and unmarshaling of the []byte type and we compare our custom marshaler with the default one. You can not only change the behavior of already supported types (like []byte) but you can also add types that aren't supported by default - in this example we add time.Duration as one such type.

Builtin unnamed golang types (like []byte) can't implement the MarshalQS and UnmarshalQS interfaces to provide their own marshaling, this is why we have to create custom QSMarshaler and QSUnmarshaler with custom factories for them.

package main

import (
	"encoding/hex"
	"fmt"
	"reflect"
	"time"

	"github.com/pamburus/qs"
)

// This example shows how to create QSMarshaler and QSUnmarshaler objects
// that have custom marshaler and unmarshaler factories to provide custom
// marshaling and unmarshaling for some types.
//
// In this example we change the default marshaling and unmarshaling of the
// []byte type and we compare our custom marshaler with the default one. You can
// not only change the behavior of already supported types (like []byte) but you
// can also add types that aren't supported by default - in this example we
// add time.Duration as one such type.
//
// Builtin unnamed golang types (like []byte) can't implement the MarshalQS and
// UnmarshalQS interfaces to provide their own marshaling, this is why we have
// to create custom QSMarshaler and QSUnmarshaler with custom factories for them.
func main() {
	customMarshaler := qs.NewMarshaler(&qs.MarshalOptions{
		MarshalerFactory: &marshalerFactory{qs.NewDefaultMarshalOptions().MarshalerFactory},
	})
	customUnmarshaler := qs.NewUnmarshaler(&qs.UnmarshalOptions{
		UnmarshalerFactory: &unmarshalerFactory{qs.NewDefaultUnmarshalOptions().UnmarshalerFactory},
	})

	performSliceTest("Default", qs.DefaultMarshaler, qs.DefaultUnmarshaler)
	performSliceTest("Custom", customMarshaler, customUnmarshaler)
	performDurationTest(customMarshaler, customUnmarshaler)

}

func performSliceTest(name string, m *qs.QSMarshaler, um *qs.QSUnmarshaler) {
	queryStr, err := m.Marshal(map[string][]byte{
		"a": {0, 1, 2},
		"b": {3, 4, 5},
	})
	fmt.Printf("%v-Marshal-Result: %v %v\n", name, queryStr, err)

	var query map[string][]byte
	err = um.Unmarshal(&query, queryStr)
	fmt.Printf("%v-Unmarshal-Result: len=%v a=%v b=%v %v\n",
		name, len(query), query["a"], query["b"], err)
}

func performDurationTest(m *qs.QSMarshaler, um *qs.QSUnmarshaler) {
	queryStr, err := m.Marshal(map[string]time.Duration{
		"duration": time.Millisecond * (61*1000 + 200),
	})
	fmt.Printf("Duration-Marshal-Result: %v %v\n", queryStr, err)

	var query map[string]time.Duration
	err = um.Unmarshal(&query, queryStr)
	fmt.Printf("Duration-Unmarshal-Result: len=%v duration=%v %v\n",
		len(query), query["duration"].String(), err)
}

var byteSliceType = reflect.TypeOf([]byte(nil))
var durationType = reflect.TypeOf(time.Duration(0))

// marshalerFactory implements the MarshalerFactory interface and provides
// custom Marshaler for the []byte type.
type marshalerFactory struct {
	orig qs.MarshalerFactory
}

func (f *marshalerFactory) Marshaler(t reflect.Type, opts *qs.MarshalOptions) (qs.Marshaler, error) {
	switch t {
	case byteSliceType:
		return byteSliceMarshaler{}, nil
	case durationType:
		return durationMarshalerInstance, nil
	default:
		return f.orig.Marshaler(t, opts)
	}
}

// unmarshalerFactory implements the UnmarshalerFactory interface and provides
// custom Unmarshaler for the []byte type.
type unmarshalerFactory struct {
	orig qs.UnmarshalerFactory
}

func (f *unmarshalerFactory) Unmarshaler(t reflect.Type, opts *qs.UnmarshalOptions) (qs.Unmarshaler, error) {
	switch t {
	case byteSliceType:
		return byteSliceMarshaler{}, nil
	case durationType:
		return durationMarshalerInstance, nil
	default:
		return f.orig.Unmarshaler(t, opts)
	}
}

// byteSliceMarshaler implements the Marshaler and Unmarshaler interfaces to
// provide custom marshaling and unmarshaling for the []byte type.
type byteSliceMarshaler struct{}

func (byteSliceMarshaler) Marshal(v reflect.Value, opts *qs.MarshalOptions) ([]string, error) {
	return []string{hex.EncodeToString(v.Interface().([]byte))}, nil
}

func (byteSliceMarshaler) Unmarshal(v reflect.Value, a []string, opts *qs.UnmarshalOptions) error {
	s, err := opts.SliceToString(a)
	if err != nil {
		return err
	}
	b, err := hex.DecodeString(s)
	if err != nil {
		return err
	}
	v.Set(reflect.ValueOf(b))
	return nil
}

var durationMarshalerInstance = &durationMarshaler{}

// durationMarshaler implements the Marshaler and Unmarshaler interfaces to
// provide custom marshaling and unmarshaling for the time.Duration type.
type durationMarshaler struct{}

func (o *durationMarshaler) Marshal(v reflect.Value, opts *qs.MarshalOptions) ([]string, error) {
	return []string{v.Interface().(time.Duration).String()}, nil
}

func (o *durationMarshaler) Unmarshal(v reflect.Value, a []string, opts *qs.UnmarshalOptions) error {
	s, err := opts.SliceToString(a)
	if err != nil {
		return err
	}
	t, err := time.ParseDuration(s)
	if err != nil {
		return fmt.Errorf("unsupported time format: %v", s)
	}
	v.Set(reflect.ValueOf(t))
	return nil
}
Output:

Default-Marshal-Result: a=0&a=1&a=2&b=3&b=4&b=5 <nil>
Default-Unmarshal-Result: len=2 a=[0 1 2] b=[3 4 5] <nil>
Custom-Marshal-Result: a=000102&b=030405 <nil>
Custom-Unmarshal-Result: len=2 a=[0 1 2] b=[3 4 5] <nil>
Duration-Marshal-Result: duration=1m1.2s <nil>
Duration-Unmarshal-Result: len=1 duration=1m1.2s <nil>
Example (DefaultOmitEmpty)

A struct field tag can mark a field with one of the keepempty and omitempty options for marshaling. If you don't use any of these options in the tag then the default marshaler uses keepempty as the default. This example creates a custom marshaler that uses omitempty as the default option. Similarly, you can change UnmarshalOptions.DefaultUnmarshalPresence to one of the Nil/Opt/Req options when calling NewUnmarshaler but this example doesn't demonstrate that.

package main

import (
	"fmt"

	"github.com/pamburus/qs"
)

func main() {
	customMarshaler := qs.NewMarshaler(&qs.MarshalOptions{
		DefaultMarshalPresence: qs.OmitEmpty,
	})

	type Query struct {
		Default   string
		KeepEmpty string `qs:",keepempty"`
		OmitEmpty string `qs:",omitempty"`
	}

	empty := &Query{}
	full := &Query{
		Default:   "Default",
		KeepEmpty: "KeepEmpty",
		OmitEmpty: "OmitEmpty",
	}

	queryStr, err := qs.Marshal(empty)
	fmt.Println("DefaultKeepEmpty-EmptyStruct:", queryStr, err)

	queryStr, err = customMarshaler.Marshal(empty)
	fmt.Println("DefaultOmitEmpty-EmptyStruct:", queryStr, err)

	queryStr, err = qs.Marshal(full)
	fmt.Println("DefaultKeepEmpty-FullStruct:", queryStr, err)

	queryStr, err = customMarshaler.Marshal(full)
	fmt.Println("DefaultOmitEmpty-FullStruct:", queryStr, err)

}
Output:

DefaultKeepEmpty-EmptyStruct: default=&keep_empty= <nil>
DefaultOmitEmpty-EmptyStruct: keep_empty= <nil>
DefaultKeepEmpty-FullStruct: default=Default&keep_empty=KeepEmpty&omit_empty=OmitEmpty <nil>
DefaultOmitEmpty-FullStruct: default=Default&keep_empty=KeepEmpty&omit_empty=OmitEmpty <nil>
Example (SelfMarshalingType)

This example shows how to implement the MarshalQS and UnmarshalQS interfaces with a custom type that wants to handle its own marshaling and unmarshaling.

package main

import (
	"encoding/hex"
	"fmt"

	"github.com/pamburus/qs"
)

// This example shows how to implement the MarshalQS and UnmarshalQS interfaces
// with a custom type that wants to handle its own marshaling and unmarshaling.
func main() {
	// Using the []byte type with its default marshaling.
	defaultMarshaling()

	// Using the Byte array type that implements custom marshaling.
	customMarshaling()

}

func defaultMarshaling() {
	queryStr, err := qs.Marshal(map[string][]byte{
		"a": {0, 1, 2},
		"b": {3, 4, 5},
	})
	fmt.Println("Default-Marshal-Result:", queryStr, err)

	var query map[string][]byte
	err = qs.Unmarshal(&query, queryStr)
	fmt.Printf("Default-Unmarshal-Result: len=%v a=%v b=%v %v\n",
		len(query), query["a"], query["b"], err)
}

func customMarshaling() {
	queryStr, err := qs.Marshal(map[string]Bytes{
		"a": {0, 1, 2},
		"b": {3, 4, 5},
	})
	fmt.Println("Custom-Marshal-Result:", queryStr, err)

	var query map[string]Bytes
	err = qs.Unmarshal(&query, queryStr)
	fmt.Printf("Custom-Unmarshal-Result: len=%v a=%v b=%v %v\n",
		len(query), query["a"], query["b"], err)
}

// Bytes implements the MarshalQS and the UnmarshalQS interfaces to marshal
// itself as a hex string instead of the usual array serialisation used in
// standard query strings.
//
// The default marshaler marshals the []byte{4, 2} array to the "key=4&key=2"
// query string. In contrast the Bytes{4, 2} array is marshaled as "key=0402".
type Bytes []byte

func (b Bytes) MarshalQS(opts *qs.MarshalOptions) ([]string, error) {
	return []string{hex.EncodeToString(b)}, nil
}

func (b *Bytes) UnmarshalQS(a []string, opts *qs.UnmarshalOptions) error {
	s, err := opts.SliceToString(a)
	if err != nil {
		return err
	}
	*b, err = hex.DecodeString(s)
	return err
}

// Compile time check: Bytes implements the qs.MarshalQS interface.
var _ qs.MarshalQS = Bytes{}

// Compile time check: *Bytes implements the qs.UnmarshalQS interface.
var _ qs.UnmarshalQS = &Bytes{}
Output:

Default-Marshal-Result: a=0&a=1&a=2&b=3&b=4&b=5 <nil>
Default-Unmarshal-Result: len=2 a=[0 1 2] b=[3 4 5] <nil>
Custom-Marshal-Result: a=000102&b=030405 <nil>
Custom-Unmarshal-Result: len=2 a=[0 1 2] b=[3 4 5] <nil>

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultMarshaler = NewMarshaler(&MarshalOptions{})

DefaultMarshaler is the marshaler used by the Marshal, MarshalValues, CanMarshal and CanMarshalType functions.

View Source
var DefaultUnmarshaler = NewUnmarshaler(&UnmarshalOptions{})

DefaultUnmarshaler is the unmarshaler used by the Unmarshal, UnmarshalValues, CanUnmarshal and CanUnmarshalType functions.

Functions

func CheckMarshal

func CheckMarshal(i interface{}) error

CheckMarshal returns an error if the type of the given object can't be marshaled into a url.Values or query string. By default only maps and structs can be marshaled into query strings given that all of their fields or values can be marshaled to []string (which is the value type of the url.Values map).

It performs the check on the type of the object without traversing or marshaling the object.

Example
m := map[string]int{}

fmt.Println(CheckMarshal(0))
fmt.Println(CheckMarshal(m))
fmt.Println(CheckMarshal(&m))
Output:

unhandled type: int
<nil>
<nil>

func CheckMarshalType

func CheckMarshalType(t reflect.Type) error

CheckMarshalType returns an error if the given type can't be marshaled into a url.Values or query string. By default only maps and structs can be marshaled int query strings given that all of their fields or values can be marshaled to []string (which is the value type of the url.Values map).

Example
intType := reflect.TypeOf(0)
mapType := reflect.TypeOf((map[string]int)(nil))

fmt.Println(CheckMarshalType(intType))
fmt.Println(CheckMarshalType(mapType))
fmt.Println(CheckMarshalType(reflect.PtrTo(mapType)))
Output:

unhandled type: int
<nil>
<nil>

func CheckUnmarshal

func CheckUnmarshal(into interface{}) error

CheckUnmarshal returns an error if the type of the given object can't be unmarshaled from a url.Vales or query string. By default only maps and structs can be unmarshaled from query strings given that all of their fields or values can be unmarshaled from []string (which is the value type of the url.Values map).

It performs the check on the type of the object without traversing or unmarshaling the object.

Example
m := map[string]int{}

fmt.Println(CheckUnmarshal(0))
fmt.Println(CheckUnmarshal(m))
fmt.Println(CheckUnmarshal(&m))
Output:

expected a pointer, got int
expected a pointer, got map[string]int
<nil>

func CheckUnmarshalType

func CheckUnmarshalType(t reflect.Type) error

CheckUnmarshalType returns an error if the given type can't be unmarshaled from a url.Vales or query string. By default only maps and structs can be unmarshaled from query strings given that all of their fields or values can be unmarshaled from []string (which is the value type of the url.Values map).

Example
intType := reflect.TypeOf(0)
mapType := reflect.TypeOf((map[string]int)(nil))

fmt.Println(CheckUnmarshalType(intType))
fmt.Println(CheckUnmarshalType(mapType))
fmt.Println(CheckUnmarshalType(reflect.PtrTo(mapType)))
Output:

expected a pointer, got int
expected a pointer, got map[string]int
<nil>

func IsRequiredFieldError

func IsRequiredFieldError(e error) (fieldName string, ok bool)

IsRequiredFieldError returns ok==false if the given error wasn't caused by a required field that was missing from the query string. Otherwise it returns the name of the missing required field with ok==true.

func Marshal

func Marshal(i interface{}) (string, error)

Marshal marshals an object into a query string. The type of the object must be supported by the ValuesMarshalerFactory of the marshaler. By default only structs and maps satisfy this condition without using a custom ValuesMarshalerFactory.

If you use a map then the key type has to be string or a type with string as its underlying type and the map value type can be anything that can be used as a struct field for marshaling.

A struct value is marshaled by adding its fields one-by-one to the query string. Only exported struct fields are marshaled. The struct field tag can contain qs package specific options in the following format:

FieldName bool `qs:"[name][,option1[,option2[...]]]"`

- If name is "-" then this field is skipped just like unexported fields.
- If name is omitted then it defaults to the snake_case of the FieldName.
  The snake_case transformation can be replaced with a field name to query
  string name converter function by creating a custom marshaler.
- For marshaling you can specify one of the keepempty and omitempty options.
  If none of them is specified then the keepempty option is the default but
  this default can be changed by using a custom marshaler object.

Examples:
FieldName bool `qs:"-"
FieldName bool `qs:"name_in_query_str"
FieldName bool `qs:"name_in_query_str,keepempty"
FieldName bool `qs:",omitempty"

Anonymous struct fields are marshaled as if their inner exported fields were fields in the outer struct.

Pointer fields are omitted when they are nil otherwise they are marshaled as the value pointed to.

Items of array and slice fields are encoded by adding multiple items with the same key to the query string. E.g.: arr=[]byte{1, 2} is encoded as "arr=1&arr=2". You can change this behavior by creating a custom marshaler with its custom MarshalerFactory that provides your custom marshal logic for the given slice and/or array types.

When a field is marshaled with the omitempty option then the field is skipped if it has the zero value of its type. A field is marshaled with the omitempty option when its tag explicitly specifies omitempty or when the tag contains neither omitempty nor keepempty but the marshaler's default marshal option is omitempty.

Example
type Query struct {
	Search   string
	Page     int
	PageSize int
}

queryString, err := Marshal(&Query{
	Search:   "my search",
	Page:     2,
	PageSize: 50,
})

if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(queryString)
}
Output:

page=2&page_size=50&search=my+search

func MarshalValues

func MarshalValues(i interface{}) (url.Values, error)

MarshalValues is the same as Marshal but returns a url.Values instead of a query string.

Example
type Query struct {
	Search   string
	Page     int
	PageSize int
}

// values is a url.Values which is a map[string][]string
values, err := MarshalValues(&Query{
	Search:   "my search",
	Page:     2,
	PageSize: 50,
})

if err != nil {
	fmt.Println(err)
} else {
	// printing the values map after sorting its keys
	var keys []string
	for key := range values {
		keys = append(keys, key)
	}
	sort.Strings(keys)
	for _, key := range keys {
		fmt.Printf("%v: %v\n", key, values[key])
	}
}
Output:

page: [2]
page_size: [50]
search: [my search]

func Unmarshal

func Unmarshal(into interface{}, queryString string) error

Unmarshal unmarshals a query string and stores the result to the object pointed to by the given pointer.

Unmarshal uses the inverse of the encodings that Marshal uses.

A struct field tag can optionally contain one of the opt, nil and req options for unmarshaling. If it contains none of these then opt is the default but the default can also be changed by using a custom marshaler. The UnmarshalPresence of a field is used only when the query string doesn't contain a value for it:

  • nil succeeds and keeps the original field value
  • opt succeeds and keeps the original field value but in case of pointer-like types (pointers, slices) with nil field value it initialises the field with a newly created object.
  • req causes the unmarshal operation to fail with an error that can be detected using qs.IsRequiredFieldError.

When unmarshaling a nil pointer field that is present in the query string the pointer is automatically initialised even if it has the nil option in its tag.

Example
type Query struct {
	Search   string
	Page     int
	PageSize int
}

var q Query
err := Unmarshal(&q, "page=2&page_size=50&search=my+search")

if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(q)
}
Output:

{my search 2 50}

func UnmarshalValues

func UnmarshalValues(into interface{}, values url.Values) error

UnmarshalValues is the same as Unmarshal but it unmarshals from a url.Values instead of a query string.

Example
type Query struct {
	Search   string
	Page     int
	PageSize int
}

var q Query
err := UnmarshalValues(&q, url.Values{
	"search":    {"my search"},
	"page":      {"2"},
	"page_size": {"50"},
})

if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(q)
}
Output:

{my search 2 50}

Types

type MarshalOptions

type MarshalOptions struct {
	// NameTransformer is used to transform struct field names into a query
	// string names when they aren't set explicitly in the struct field tag.
	// If this field is nil then NewMarshaler uses a default function that
	// converts the CamelCase field names to snake_case which is popular
	// with query strings.
	NameTransformer NameTransformFunc

	// ValuesMarshalerFactory is used by QSMarshaler to create ValuesMarshaler
	// objects for specific types. If this field is nil then NewMarshaler uses
	// a default builtin factory.
	ValuesMarshalerFactory ValuesMarshalerFactory

	// MarshalerFactory is used by QSMarshaler to create Marshaler
	// objects for specific types. If this field is nil then NewMarshaler uses
	// a default builtin factory.
	MarshalerFactory MarshalerFactory

	// DefaultMarshalPresence is used for the marshaling of struct fields that
	// don't have an explicit MarshalPresence option set in their tags.
	// This option is used for every item when you marshal a map[string]WhateverType
	// instead of a struct because map items can't have a tag to override this.
	DefaultMarshalPresence MarshalPresence
}

MarshalOptions is used as a parameter by the NewMarshaler function.

func NewDefaultMarshalOptions

func NewDefaultMarshalOptions() *MarshalOptions

NewDefaultMarshalOptions creates a new MarshalOptions in which every field is set to its default value.

type MarshalPresence

type MarshalPresence int

MarshalPresence is an enum that controls the marshaling of empty fields. A field is empty if it has its zero value or it is an empty container.

const (
	// MPUnspecified is the zero value of MarshalPresence. In most cases
	// you will use this implicitly by simply leaving the
	// MarshalOptions.DefaultMarshalPresence field uninitialised which results
	// in using the default MarshalPresence which is KeepEmpty.
	MPUnspecified MarshalPresence = iota

	// KeepEmpty marshals the values of empty fields into the marshal output.
	KeepEmpty

	// OmitEmpty doesn't marshal the values of empty fields into the marshal output.
	OmitEmpty
)

func (MarshalPresence) String

func (v MarshalPresence) String() string

type MarshalQS

type MarshalQS interface {
	// MarshalQS is essentially the same as the Marshaler.Marshal
	// method without its v parameter.
	MarshalQS(opts *MarshalOptions) ([]string, error)
}

MarshalQS is an interface that can be implemented by any type that wants to handle its own marshaling instead of relying on the default marshaling provided by this package.

type Marshaler

type Marshaler interface {
	// Marshal marshals the given v value using opts into a []string.
	// Note that []string is the value type of the standard url.Values which is
	// a map[string][]string.
	Marshal(v reflect.Value, opts *MarshalOptions) ([]string, error)
}

Marshaler can marshal a reflect.Value into a []string.

type MarshalerFactory

type MarshalerFactory interface {
	// Marshaler returns a Marshaler object for the given t type and opts
	// options.
	Marshaler(t reflect.Type, opts *MarshalOptions) (Marshaler, error)
}

MarshalerFactory can create Marshaler objects for various types.

type NameTransformFunc

type NameTransformFunc func(string) string

A NameTransformFunc is used to derive the query string keys from the field names of the struct. NameTransformFunc is the type of the DefaultNameTransform, MarshalOptions.NameTransformer and UnmarshalOptions.NameTransformer variables.

type QSMarshaler

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

QSMarshaler objects can be created by calling NewMarshaler and they can be used to marshal structs or maps into query strings or url.Values.

func NewMarshaler

func NewMarshaler(opts *MarshalOptions) *QSMarshaler

NewMarshaler returns a new QSMarshaler object.

func (*QSMarshaler) CheckMarshal

func (p *QSMarshaler) CheckMarshal(i interface{}) error

CheckMarshal check whether the type of the given object supports marshaling into query strings. See the documentation of the global CheckMarshal func.

func (*QSMarshaler) CheckMarshalType

func (p *QSMarshaler) CheckMarshalType(t reflect.Type) error

CheckMarshalType check whether the given type supports marshaling into query strings. See the documentation of the global CheckMarshalType func.

func (*QSMarshaler) Marshal

func (p *QSMarshaler) Marshal(i interface{}) (string, error)

Marshal marshals a given object into a query string. See the documentation of the global Marshal func.

func (*QSMarshaler) MarshalValues

func (p *QSMarshaler) MarshalValues(i interface{}) (url.Values, error)

MarshalValues marshals a given object into a url.Values. See the documentation of the global MarshalValues func.

type QSUnmarshaler

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

QSUnmarshaler objects can be created by calling NewUnmarshaler and they can be used to unmarshal query strings or url.Values into structs or maps.

func NewUnmarshaler

func NewUnmarshaler(opts *UnmarshalOptions) *QSUnmarshaler

NewUnmarshaler returns a new QSUnmarshaler object.

func (*QSUnmarshaler) CheckUnmarshal

func (p *QSUnmarshaler) CheckUnmarshal(into interface{}) error

CheckUnmarshal check whether the type of the given object supports unmarshaling from query strings. See the documentation of the global CheckUnmarshal func.

func (*QSUnmarshaler) CheckUnmarshalType

func (p *QSUnmarshaler) CheckUnmarshalType(t reflect.Type) error

CheckUnmarshalType check whether the given type supports unmarshaling from query strings. See the documentation of the global CheckUnmarshalType func.

func (*QSUnmarshaler) Unmarshal

func (p *QSUnmarshaler) Unmarshal(into interface{}, queryString string) error

Unmarshal unmarshals an object from a query string. See the documentation of the global Unmarshal func.

func (*QSUnmarshaler) UnmarshalValues

func (p *QSUnmarshaler) UnmarshalValues(into interface{}, values url.Values) error

UnmarshalValues unmarshals an object from a url.Values. See the documentation of the global UnmarshalValues func.

type UnmarshalOptions

type UnmarshalOptions struct {
	// NameTransformer is used to transform struct field names into a query
	// string names when they aren't set explicitly in the struct field tag.
	// If this field is nil then NewUnmarshaler uses a default function that
	// converts the CamelCase field names to snake_case which is popular
	// with query strings.
	NameTransformer NameTransformFunc

	// SliceToString is used by Unmarshaler.Unmarshal when it unmarshals into a
	// primitive non-array struct field. In such cases unmarshaling a []string
	// (which is the value type of the url.Values map) requires transforming
	// the []string into a single string before unmarshaling.
	//
	// E.g.: If you have a struct field "Count int" but you receive a query
	// string "count=5&count=6&count=8" then the incoming []string{"5", "6", "8"}
	// has to be converted into a single string before setting the "Count int"
	// field.
	//
	// If you don't initialise this field then a default function is used that
	// fails if the input array doesn't contain exactly one item.
	//
	// In some cases you might want to provide your own function that is more
	// forgiving. E.g.: you can provide a function that picks the first or last
	// item, or concatenates/joins the whole list into a single string.
	SliceToString func([]string) (string, error)

	// ValuesUnmarshalerFactory is used by QSUnmarshaler to create ValuesUnmarshaler
	// objects for specific types. If this field is nil then NewUnmarshaler uses
	// a default builtin factory.
	ValuesUnmarshalerFactory ValuesUnmarshalerFactory

	// UnmarshalerFactory is used by QSUnmarshaler to create Unmarshaler
	// objects for specific types. If this field is nil then NewUnmarshaler uses
	// a default builtin factory.
	UnmarshalerFactory UnmarshalerFactory

	// DefaultUnmarshalPresence is used for the unmarshaling of struct fields
	// that don't have an explicit UnmarshalPresence option set in their tags.
	DefaultUnmarshalPresence UnmarshalPresence
}

UnmarshalOptions is used as a parameter by the NewUnmarshaler function.

func NewDefaultUnmarshalOptions

func NewDefaultUnmarshalOptions() *UnmarshalOptions

NewDefaultUnmarshalOptions creates a new UnmarshalOptions in which every field is set to its default value.

type UnmarshalPresence

type UnmarshalPresence int

UnmarshalPresence is an enum that controls the unmarshaling of fields. This option is used by the unmarshaler only if the given field isn't present in the query string or url.Values that is being unmarshaled.

const (
	// UPUnspecified is the zero value of UnmarshalPresence. In most cases
	// you will use this implicitly by simply leaving the
	// UnmarshalOptions.DefaultUnmarshalPresence field uninitialised which results
	// in using the default UnmarshalPresence which is Opt.
	UPUnspecified UnmarshalPresence = iota

	// Opt tells the unmarshaler to leave struct fields as they are when they
	// aren't present in the query string. However, nil pointers and arrays are
	// created and initialised with new objects.
	Opt

	// Nil is the same as Opt except that it doesn't initialise nil pointers
	// and slices during unmarshal when they are missing from the query string.
	Nil

	// Req tells the unmarshaler to fail with an error that can be detected
	// using qs.IsRequiredFieldError if the given field is
	// missing from the query string. While this is rather validation than
	// unmarshaling it is practical to have this in case of simple programs.
	// If you don't want to mix unmarshaling and validation then you can use the
	// Nil option instead with nil pointers and nil arrays to be able to detect
	// missing fields after unmarshaling.
	Req
)

func (UnmarshalPresence) String

func (v UnmarshalPresence) String() string

type UnmarshalQS

type UnmarshalQS interface {
	// UnmarshalQS is essentially the same as the Unmarshaler.Unmarshal
	// method without its v parameter.
	UnmarshalQS(a []string, opts *UnmarshalOptions) error
}

UnmarshalQS is an interface that can be implemented by any type that wants to handle its own unmarshaling instead of relying on the default unmarshaling provided by this package.

type Unmarshaler

type Unmarshaler interface {
	// Unmarshal unmarshals the given []string using opts into v.
	//
	// If the query string doesn't contain a key for this field then Unmarshal
	// is called only if the UnmarshalPresence option of the field is Opt
	// and in that case a == nil. In such cases pointer like types (pointers,
	// arrays, maps) should initialise nil pointers with an empty object.
	// With Nil or Req options this Unmarshal method isn't called.
	//
	// The []string is the value type of the url.Values map. If your unmarshaler
	// expects only a single string value instead of an array then you can call
	// opts.SliceToString(a).
	Unmarshal(v reflect.Value, a []string, opts *UnmarshalOptions) error
}

Unmarshaler can unmarshal a []string (which is the value type of the url.Values map) into a reflect.Value.

type UnmarshalerFactory

type UnmarshalerFactory interface {
	// Unmarshaler returns an Unmarshaler object for the given t type and opts
	// options.
	Unmarshaler(t reflect.Type, opts *UnmarshalOptions) (Unmarshaler, error)
}

UnmarshalerFactory can create Unmarshaler objects for various types.

type ValuesMarshaler

type ValuesMarshaler interface {
	// MarshalValues marshals the given v value using opts into a url.Values.
	MarshalValues(v reflect.Value, opts *MarshalOptions) (url.Values, error)
}

ValuesMarshaler can marshal a value into a url.Values.

type ValuesMarshalerFactory

type ValuesMarshalerFactory interface {
	// ValuesMarshaler returns a ValuesMarshaler object for the given t type and
	// opts options.
	ValuesMarshaler(t reflect.Type, opts *MarshalOptions) (ValuesMarshaler, error)
}

ValuesMarshalerFactory can create ValuesMarshaler objects for various types.

type ValuesUnmarshaler

type ValuesUnmarshaler interface {
	// UnmarshalValues unmarshals the given url.Values using opts into v.
	UnmarshalValues(v reflect.Value, vs url.Values, opts *UnmarshalOptions) error
}

ValuesUnmarshaler can unmarshal a url.Values into a value.

type ValuesUnmarshalerFactory

type ValuesUnmarshalerFactory interface {
	// ValuesUnmarshaler returns a ValuesUnmarshaler object for the given t
	// type and opts options.
	ValuesUnmarshaler(t reflect.Type, opts *UnmarshalOptions) (ValuesUnmarshaler, error)
}

ValuesUnmarshalerFactory can create ValuesUnmarshaler objects for various types.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL