coder
Introduced in v0.15.0. For backward compatibility, decoder
(introduced in v0.10.0) now is an alias of coder
.
coder is a SPECIAL directive executor who overrides the coder that used to encode/decode the value of the corresponding field.
Signature
Name: "coder" | "decoder"
Args: CODER_NAME
When there's a coder directive defined for a field, the specified named decoder will be used rather than the default one which is auto-selected by the type of the field.
Usage
import httpin_core "github.com/ggicci/httpin/core"
type MyDate time.Time // adapted time.Time to MyDate, MyDate must implement httpin_core.Stringable
func (t MyDate) ToString() (string, error) {
return time.Time(t).Format("2006-01-02"), nil
}
func (t *MyDate) FromString(value string) error {
v, err := time.Parse("2006-01-02", value)
if err != nil {
return &InvalidDate{Value: value, Err: err}
}
*t = MyDate(v)
return nil
}
func init() {
// Before using the named coder, you need to register it.
httpin_core.RegisterNamedCoder[time.Time]("date", func(t *time.Time) (httpin_core.Stringable, error) {
return (*MyDate)(t), nil
})
}
type ListUsersInput struct {
Gender string `in:"form=gender"`
// By default, the decoder is auto-selected by the field type, which is of `time.Time`.
// When coder directive is set, the specified named coder "date" will be used instead.
Birthday time.Time `in:"form=birthday;coder=date"`
}
Runable Example
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"time"
"github.com/ggicci/httpin"
httpin_core "github.com/ggicci/httpin/core"
"github.com/justinas/alice"
)
type MyDate time.Time // adapted time.Time to MyDate, MyDate must implement httpin_core.Stringable
func (t MyDate) ToString() (string, error) {
return time.Time(t).Format("2006-01-02"), nil
}
func (t *MyDate) FromString(value string) error {
v, err := time.Parse("2006-01-02", value)
if err != nil {
return fmt.Errorf("invalid date: %w", err)
}
*t = MyDate(v)
return nil
}
func init() {
httpin_core.RegisterNamedCoder[time.Time]("date", func(t *time.Time) (httpin_core.Stringable, error) {
return (*MyDate)(t), nil
})
}
type ListUsersInput struct {
Gender string `in:"form=gender"`
// By default, the decoder is auto-selected by the field type, which is of `time.Time`.
// When decoder directive is set, the specified named decoder "date" will be used instead.
Birthday time.Time `in:"form=birthday;coder=date"`
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
fmt.Printf("input: %#v\n", input)
}
func main() {
mux := http.NewServeMux()
mux.Handle("/users", alice.New(
httpin.NewInput(ListUsersInput{}),
).ThenFunc(ListUsers))
r, _ := http.NewRequest("GET", "/users?gender=male&birthday=1991-11-10", nil)
rw := httptest.NewRecorder()
mux.ServeHTTP(rw, r)
}