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.
- Subjective improvements
- Added go-stringer generator for enums
- Union duplicated code in cache structs to generic cacher
- Improved custom marshaler workflow
- Added register handlers instead of composition
- Added split/merge slice values with separator
- Added option to supress error on unmarshal unexpected value in slice field
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/dmji/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>
}- Support for primitive types (
bool,int, etc...), pointers, slices, arrays, maps, structs,time.Timeandurl.URL. - A custom type can implement the
MarshalQSand/orUnmarshalQSinterfaces 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
[]bytearray 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) thenencoding/jsonand 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
keepemptyandomitemptyoptions the marshaler useskeepemptyby default. By creating a custom marshaler you can change the default toomitempty. - When a struct field tag doesn't specify any of the
opt,nil,reqoptions the unmarshaler usesoptby 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,omitemptyoptions for marshaling. - Set one of the
opt,nil,reqoptions for unmarshaling.
- Exclude a field from marshaling/unmarshaling by specifying
The godoc of the qs package contains more detailed documentation with working examples.