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.
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>
}
- Support for primitive types (
bool
,int
, etc...), pointers, slices, arrays, maps, structs,time.Time
andurl.URL
. - A custom type can implement the
MarshalQS
and/orUnmarshalQS
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) thenencoding/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
andomitempty
options the marshaler useskeepempty
by 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
,req
options the unmarshaler usesopt
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.
- Exclude a field from marshaling/unmarshaling by specifying
The godoc of the qs package contains more detailed documentation with working examples.