API Reference
7 minute read
Detailed API reference for all exported types, functions, and interfaces in the rivaas.dev/binding package.
Core Binding Functions
Generic API
JSON
func JSON[T any](data []byte, opts ...Option) (T, error)
Binds JSON data to a struct of type T.
Parameters:
data: JSON bytes to parseopts: Optional configuration options
Returns:
- Populated struct of type
T - Error if binding fails
Example:
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
user, err := binding.JSON[User](jsonData)
JSONReader
func JSONReader[T any](r io.Reader, opts ...Option) (T, error)
Binds JSON from an io.Reader. More memory-efficient for large payloads.
Example:
user, err := binding.JSONReader[User](r.Body)
Query
func Query[T any](values url.Values, opts ...Option) (T, error)
Binds URL query parameters to a struct.
Parameters:
values: URL query values (r.URL.Query())opts: Optional configuration options
Example:
type Params struct {
Page int `query:"page" default:"1"`
Limit int `query:"limit" default:"20"`
Tags []string `query:"tags"`
}
params, err := binding.Query[Params](r.URL.Query())
Form
func Form[T any](values url.Values, opts ...Option) (T, error)
Binds form data to a struct.
Parameters:
values: Form values (r.Formorr.PostForm)opts: Optional configuration options
Example:
type LoginForm struct {
Username string `form:"username"`
Password string `form:"password"`
}
form, err := binding.Form[LoginForm](r.PostForm)
Header
func Header[T any](headers http.Header, opts ...Option) (T, error)
Binds HTTP headers to a struct.
Example:
type Headers struct {
APIKey string `header:"X-API-Key"`
RequestID string `header:"X-Request-ID"`
}
headers, err := binding.Header[Headers](r.Header)
Cookie
func Cookie[T any](cookies []*http.Cookie, opts ...Option) (T, error)
Binds HTTP cookies to a struct.
Example:
type Cookies struct {
SessionID string `cookie:"session_id"`
Theme string `cookie:"theme" default:"light"`
}
cookies, err := binding.Cookie[Cookies](r.Cookies())
Path
func Path[T any](params map[string]string, opts ...Option) (T, error)
Binds URL path parameters to a struct.
Example:
type PathParams struct {
UserID int `path:"user_id"`
}
// With gorilla/mux or chi
params, err := binding.Path[PathParams](mux.Vars(r))
XML
func XML[T any](data []byte, opts ...Option) (T, error)
Binds XML data to a struct.
Example:
type Document struct {
Title string `xml:"title"`
Body string `xml:"body"`
}
doc, err := binding.XML[Document](xmlData)
XMLReader
func XMLReader[T any](r io.Reader, opts ...Option) (T, error)
Binds XML from an io.Reader.
Bind (Multi-Source)
func Bind[T any](sources ...Source) (T, error)
Binds from multiple sources with precedence.
Example:
type Request struct {
UserID int `query:"user_id" json:"user_id"`
APIKey string `header:"X-API-Key"`
}
req, err := binding.Bind[Request](
binding.FromQuery(r.URL.Query()),
binding.FromJSON(r.Body),
binding.FromHeader(r.Header),
)
Non-Generic API
JSONTo
func JSONTo(data []byte, target interface{}, opts ...Option) error
Binds JSON to a pointer. Use when type comes from a variable.
Example:
var user User
err := binding.JSONTo(jsonData, &user)
Similar non-generic functions exist for all sources:
QueryTo(values url.Values, target interface{}, opts ...Option) errorFormTo(values url.Values, target interface{}, opts ...Option) errorHeaderTo(headers http.Header, target interface{}, opts ...Option) errorCookieTo(cookies []*http.Cookie, target interface{}, opts ...Option) errorPathTo(params map[string]string, target interface{}, opts ...Option) errorXMLTo(data []byte, target interface{}, opts ...Option) error
Source Constructors
For multi-source binding:
func FromJSON(r io.Reader) Source
func FromQuery(values url.Values) Source
func FromForm(values url.Values) Source
func FromHeader(headers http.Header) Source
func FromCookie(cookies []*http.Cookie) Source
func FromPath(params map[string]string) Source
func FromXML(r io.Reader) Source
Binder Type
Constructor
func New(opts ...Option) (*Binder, error)
func MustNew(opts ...Option) *Binder
Creates a reusable binder with configuration.
Example:
binder := binding.MustNew(
binding.WithConverter[uuid.UUID](uuid.Parse),
binding.WithMaxDepth(16),
)
user, err := binder.JSON[User](data)
Binder Methods
A Binder has the same methods as the package-level functions:
func (b *Binder) JSON[T any](data []byte, opts ...Option) (T, error)
func (b *Binder) Query[T any](values url.Values, opts ...Option) (T, error)
// ... etc for all binding functions
Error Types
BindError
Field-specific binding error with detailed context:
type BindError struct {
Field string // Field name that failed to bind
Source string // Source ("query", "json", "header", etc.)
Value string // Raw value that failed to bind
Type string // Expected Go type
Reason string // Human-readable reason
Err error // Underlying error
}
func (e *BindError) Error() string
func (e *BindError) Unwrap() error
func (e *BindError) IsType() bool // True if type conversion failed
func (e *BindError) IsMissing() bool // True if required field missing
Example:
user, err := binding.JSON[User](data)
if err != nil {
var bindErr *binding.BindError
if errors.As(err, &bindErr) {
log.Printf("Field %s from %s failed: %v",
bindErr.Field, bindErr.Source, bindErr.Err)
}
}
UnknownFieldError
Returned in strict mode when unknown fields are encountered:
type UnknownFieldError struct {
Fields []string // List of unknown field names
}
func (e *UnknownFieldError) Error() string
Example:
user, err := binding.JSON[User](data, binding.WithStrictJSON())
if err != nil {
var unknownErr *binding.UnknownFieldError
if errors.As(err, &unknownErr) {
log.Printf("Unknown fields: %v", unknownErr.Fields)
}
}
MultiError
Multiple errors collected with WithAllErrors():
type MultiError struct {
Errors []*BindError
}
func (e *MultiError) Error() string
func (e *MultiError) Unwrap() []error
Example:
user, err := binding.JSON[User](data, binding.WithAllErrors())
if err != nil {
var multi *binding.MultiError
if errors.As(err, &multi) {
for _, e := range multi.Errors {
log.Printf("Field %s: %v", e.Field, e.Err)
}
}
}
Interfaces
ValueGetter
Interface for custom data sources:
type ValueGetter interface {
Get(key string) string // Get first value for key
GetAll(key string) []string // Get all values for key
Has(key string) bool // Check if key exists
}
Example Implementation:
type EnvGetter struct{}
func (g *EnvGetter) Get(key string) string {
return os.Getenv(key)
}
func (g *EnvGetter) GetAll(key string) []string {
if val := os.Getenv(key); val != "" {
return []string{val}
}
return nil
}
func (g *EnvGetter) Has(key string) bool {
_, exists := os.LookupEnv(key)
return exists
}
ConverterFunc
Function type for custom type converters:
type ConverterFunc[T any] func(string) (T, error)
Example:
func ParseEmail(s string) (Email, error) {
if !strings.Contains(s, "@") {
return "", errors.New("invalid email")
}
return Email(s), nil
}
binder := binding.MustNew(
binding.WithConverter[Email](ParseEmail),
)
Helper Functions
MapGetter
Converts a map[string]string to a ValueGetter:
func MapGetter(m map[string]string) ValueGetter
Example:
data := map[string]string{"name": "Alice", "age": "30"}
getter := binding.MapGetter(data)
result, err := binding.RawInto[User](getter, "custom")
MultiMapGetter
Converts a map[string][]string to a ValueGetter:
func MultiMapGetter(m map[string][]string) ValueGetter
Example:
data := map[string][]string{
"tags": {"go", "rust"},
"name": {"Alice"},
}
getter := binding.MultiMapGetter(data)
result, err := binding.RawInto[User](getter, "custom")
GetterFunc
Adapts a function to the ValueGetter interface:
type GetterFunc func(key string) ([]string, bool)
func (f GetterFunc) Get(key string) string
func (f GetterFunc) GetAll(key string) []string
func (f GetterFunc) Has(key string) bool
Example:
getter := binding.GetterFunc(func(key string) ([]string, bool) {
if val, ok := myMap[key]; ok {
return []string{val}, true
}
return nil, false
})
Raw/RawInto
Low-level binding from custom ValueGetter:
func Raw[T any](getter ValueGetter, source string, opts ...Option) (T, error)
func RawInto(getter ValueGetter, source string, target interface{}, opts ...Option) error
Events and Observability
Events Type
Hooks for observing binding operations:
type Events struct {
FieldBound func(name, tag string)
UnknownField func(name string)
Done func(stats Stats)
}
Example:
binder := binding.MustNew(
binding.WithEvents(binding.Events{
FieldBound: func(name, tag string) {
log.Printf("Bound field %s from %s", name, tag)
},
UnknownField: func(name string) {
log.Printf("Unknown field: %s", name)
},
Done: func(stats binding.Stats) {
log.Printf("Binding completed: %d fields, %d errors",
stats.FieldsBound, stats.ErrorCount)
},
}),
)
Stats Type
Statistics from binding operation:
type Stats struct {
FieldsBound int // Number of fields successfully bound
ErrorCount int // Number of errors encountered
Duration time.Duration // Time taken for binding
}
Constants
Slice Modes
const (
SliceRepeat SliceMode = iota // Repeated params: ?tags=a&tags=b (default)
SliceCSV // CSV params: ?tags=a,b,c
)
Unknown Field Handling
const (
UnknownIgnore UnknownMode = iota // Ignore unknown fields (default)
UnknownWarn // Log warning for unknown fields
UnknownError // Error on unknown fields
)
Merge Strategies
const (
MergeLastWins MergeStrategy = iota // Last source wins (default)
MergeFirstWins // First source wins
)
Default Values
Time Layouts
var DefaultTimeLayouts = []string{
time.RFC3339,
time.RFC3339Nano,
time.RFC1123,
time.RFC1123Z,
time.RFC822,
time.RFC822Z,
time.RFC850,
time.ANSIC,
time.UnixDate,
time.RubyDate,
time.Kitchen,
time.Stamp,
time.StampMilli,
time.StampMicro,
time.StampNano,
time.DateTime,
time.DateOnly,
time.TimeOnly,
"2006-01-02",
"01/02/2006",
"2006/01/02",
}
Can be extended with WithTimeLayouts().
Type Constraints
Supported Interface Types
Types implementing these interfaces are automatically supported:
encoding.TextUnmarshaler: For custom text unmarshalingjson.Unmarshaler: For custom JSON unmarshalingxml.Unmarshaler: For custom XML unmarshaling
Example:
type Status string
func (s *Status) UnmarshalText(text []byte) error {
// Custom parsing logic
*s = Status(string(text))
return nil
}
type Request struct {
Status Status `query:"status"` // Automatically uses UnmarshalText
}
Thread Safety
All package-level functions and Binder methods are safe for concurrent use. The struct reflection cache is thread-safe and has no size limit.
See Also
- Options Reference - All configuration options
- Sub-Packages - YAML, TOML, MessagePack, Protocol Buffers
- Performance - Benchmarks and optimization
- Troubleshooting - Common issues and solutions
For usage examples, see the Binding Guide.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.