Web Analytics

qs

⭐ 82 stars English by sonh

qs #

Build Codecov GoReportCard Release PkgGoDev MIT License

Zero-dependencies package to encodes structs into url.Values.

Installation

go get github.com/sonh/qs

Usage

import (
    "github.com/sonh/qs"
)
Package qs exports the NewEncoder() function to create an encoder.

The encoder caches struct information to speed up the encoding process; using a single instance is highly recommended.

Use the WithTagAlias() function to register a custom tag alias (the default is qs).

encoder = qs.NewEncoder(
    qs.WithTagAlias("myTag"),
)

Encoder has Values() and Encode() functions to encode structs into url.Values.

Supported data types:

Example

type Query struct {
    Tags   []string  qs:"tags"
    Limit  int       qs:"limit"
    From   time.Time qs:"from"
    Active bool      qs:"active,omitempty"  //omit empty value
    Ignore float64   qs:"-"                 //ignore
}

query := &Query{ Tags: []string{"docker", "golang", "reactjs"}, Limit: 24, From: time.Unix(1580601600, 0).UTC(), Ignore: 0, }

encoder := qs.NewEncoder() values, err := encoder.Values(query) if err != nil { // Handle error } fmt.Println(values.Encode()) //(unescaped) output: "from=2020-02-02T00:00:00Z&limit=24&tags=docker&tags=golang&tags=reactjs"

Bool format

Use int option to encode bool to integer
type Query struct {
    DefaultFmt bool qs:"default_fmt"
    IntFmt     bool qs:"int_fmt,int"
}

query := &Query{ DefaultFmt: true, IntFmt: true, } values, _ := encoder.Values(query) fmt.Println(values.Encode()) // (unescaped) output: "default_fmt=true&int_fmt=1"

Time format

By default, the package encodes time.Time values in RFC3339 format.

Include the "second" or "millis" option to indicate that the field should be encoded as seconds or milliseconds.

type Query struct {
    Default time.Time   qs:"default_fmt"
    Second  time.Time   qs:"second_fmt,second" //use second option
    Millis  time.Time   qs:"millis_fmt,millis" //use millis option
}

t := time.Unix(1580601600, 0).UTC() query := &Query{ Default: t, Second: t, Millis: t, }

encoder := qs.NewEncoder() values, _ := encoder.Values(query) fmt.Println(values.Encode()) // (unescaped) output: "default_fmt=2020-02-02T00:00:00Z&millis_fmt=1580601600000&second_fmt=1580601600"

Slice/Array Format

Slice and Array default to encoding into multiple URL values with the same key name.
type Query struct {
    Tags []string qs:"tags"
}

values, _ := encoder.Values(&Query{Tags: []string{"foo","bar"}}) fmt.Println(values.Encode()) //(unescaped) output: "tags=foo&tags=bar"

Including the comma option to signal that the field should be encoded as a single comma-delimited value.

type Query struct {
    Tags []string qs:"tags,comma"
}

values, _ := encoder.Values(&Query{Tags: []string{"foo","bar"}}) fmt.Println(values.Encode()) //(unescaped) output: "tags=foo,bar"

Including the bracket option to signal that the multiple URL values should have "[]" appended to the value name.

type Query struct {
    Tags []string qs:"tags,bracket"
}

values, _ := encoder.Values(&Query{Tags: []string{"foo","bar"}}) fmt.Println(values.Encode()) //(unescaped) output: "tags[]=foo&tags[]=bar"

The index option will append an index number with brackets to the value name.

type Query struct {
    Tags []string qs:"tags,index"
}

values, _ := encoder.Values(&Query{Tags: []string{"foo","bar"}}) fmt.Println(values.Encode()) //(unescaped) output: "tags[0]=foo&tags[1]=bar"

Nested structs

All nested structs are encoded including the parent value name with brackets for scoping.

type User struct {
    Verified bool      qs:"verified"
    From     time.Time qs:"from,millis"
}

type Query struct { User User qs:"user" }

query := Query{ User: User{ Verified: true, From: time.Now(), }, } values, _ := encoder.Values(query) fmt.Println(values.Encode()) //(unescaped) output: "user[from]=1601623397728&user[verified]=true"

By default, it uses the brackets, add the dot option to a nested struct field to scope its children with .:

type Query struct {
    User User qs:"user,dot"
}

values, _ := encoder.Values(query) fmt.Println(values.Encode()) //(unescaped) output: "user.from=1601623397728&user.verified=true"

The dot option applies only to the field it is declared on; nest it again on a deeper struct field to keep using dots (otherwise that level falls back to brackets).

Custom Type

Implement funcs:
type NullableName struct {
	First string
	Last  string
}

func (n NullableName) EncodeParam() (string, error) { return n.First + n.Last, nil }

func (n NullableName) IsZero() bool { return n.First == "" && n.Last == "" }

type Struct struct { User NullableName qs:"user" Admin NullableName qs:"admin,omitempty" }

s := Struct{ User: NullableName{ First: "son", Last: "huynh", }, } encoder := qs.NewEncoder()

values, err := encoder.Values(&s) if err != nil { // Handle error fmt.Println("failed") return } fmt.Println(values.Encode()) //(unescaped) output: "user=sonhuynh"

Limitation

_Will improve in future versions_

License

Distributed under MIT License, please see license file in code for more details.

--- Tranlated By Open Ai Tx | Last indexed: 2026-07-29 ---