Binding Package

Complete API reference for the rivaas.dev/binding package

Complete API reference documentation for the rivaas.dev/binding package - high-performance request data binding for Go web applications.

Package Information

Overview

The binding package provides a high-performance, type-safe way to bind request data from various sources (query parameters, JSON bodies, headers, etc.) into Go structs using struct tags.

import "rivaas.dev/binding"

type CreateUserRequest struct {
    Username string `json:"username"`
    Email    string `json:"email"`
    Age      int    `json:"age"`
}

// Generic API (preferred)
user, err := binding.JSON[CreateUserRequest](body)

Key Features

  • Type-Safe Generic API: Compile-time type safety with zero runtime overhead
  • Multiple Sources: Query, path, form, header, cookie, JSON, XML, YAML, TOML, MessagePack, Protocol Buffers
  • Zero Allocation: Struct reflection info cached for optimal performance
  • Flexible Type Support: Primitives, time types, collections, nested structs, custom types
  • Detailed Errors: Field-level error information with context
  • Extensible: Custom type converters and value getters
  • Multi-Source Binding: Combine data from multiple sources with precedence control

Package Structure

graph TB
    A[binding] --> B[Core API]
    A --> C[Sub-Packages]
    
    B --> B1[JSON/XML/Form]
    B --> B2[Query/Header/Cookie]
    B --> B3[Multi-Source]
    B --> B4[Custom Binders]
    
    C --> C1[yaml]
    C --> C2[toml]
    C --> C3[msgpack]
    C --> C4[proto]
    
    style A fill:#e1f5ff
    style B fill:#fff3cd
    style C fill:#d4edda

Quick Navigation

API Documentation

Performance and Troubleshooting

Learning Resources

Core API

Generic Functions

Type-safe binding with compile-time guarantees:

// JSON binding
func JSON[T any](data []byte, opts ...Option) (T, error)

// Query parameter binding
func Query[T any](values url.Values, opts ...Option) (T, error)

// Form data binding
func Form[T any](values url.Values, opts ...Option) (T, error)

// Header binding
func Header[T any](headers http.Header, opts ...Option) (T, error)

// Cookie binding
func Cookie[T any](cookies []*http.Cookie, opts ...Option) (T, error)

// Path parameter binding
func Path[T any](params map[string]string, opts ...Option) (T, error)

// XML binding
func XML[T any](data []byte, opts ...Option) (T, error)

// Multi-source binding
func Bind[T any](sources ...Source) (T, error)

Non-Generic Functions

For cases where type comes from a variable:

// JSON binding to pointer
func JSONTo(data []byte, target interface{}, opts ...Option) error

// Query binding to pointer
func QueryTo(values url.Values, target interface{}, opts ...Option) error

// ... similar for other sources

Reader Variants

Stream from io.Reader for large payloads:

func JSONReader[T any](r io.Reader, opts ...Option) (T, error)
func XMLReader[T any](r io.Reader, opts ...Option) (T, error)

Type System

Built-in Type Support

CategoryTypes
Primitivesstring, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, bool
Timetime.Time, time.Duration
Networknet.IP, net.IPNet, url.URL
Regexregexp.Regexp
Collections[]T, map[string]T
Pointers*T for any supported type
NestedNested structs with dot notation

Custom Types

Register custom converters for unsupported types:

import "github.com/google/uuid"

binder := binding.MustNew(
    binding.WithConverter[uuid.UUID](uuid.Parse),
)

Struct Tags

Control binding behavior with struct tags:

TagPurposeExample
jsonJSON body fieldjson:"field_name"
queryQuery parameterquery:"param_name"
formForm dataform:"field_name"
headerHTTP headerheader:"X-Header-Name"
pathPath parameterpath:"param_name"
cookieHTTP cookiecookie:"cookie_name"
defaultDefault valuedefault:"value"
validateValidation rulesvalidate:"required,email"

Error Types

BindError

Field-specific binding error:

type BindError struct {
    Field  string // Field name
    Source string // Source ("query", "json", etc.)
    Value  string // Raw value
    Type   string // Expected type
    Reason string // Error reason
    Err    error  // Underlying error
}

UnknownFieldError

Unknown fields in strict mode:

type UnknownFieldError struct {
    Fields []string // List of unknown fields
}

MultiError

Multiple errors with WithAllErrors():

type MultiError struct {
    Errors []*BindError
}

Configuration Options

Common options for all binding functions:

// Security limits
binding.WithMaxDepth(16)        // Max struct nesting
binding.WithMaxSliceLen(1000)   // Max slice elements
binding.WithMaxMapSize(500)     // Max map entries

// Unknown fields
binding.WithStrictJSON()         // Fail on unknown fields
binding.WithUnknownFields(mode)  // UnknownError/UnknownWarn/UnknownIgnore

// Slice parsing
binding.WithSliceMode(mode)      // SliceRepeat or SliceCSV

// Error collection
binding.WithAllErrors()          // Collect all errors instead of failing on first

Reusable Binders

Create configured binder instances:

binder := binding.MustNew(
    binding.WithConverter[uuid.UUID](uuid.Parse),
    binding.WithTimeLayouts("2006-01-02", "01/02/2006"),
    binding.WithMaxDepth(16),
)

// Use across handlers
user, err := binder.JSON[User](body)
params, err := binder.Query[Params](values)

Sub-Packages

Additional format support via sub-packages:

PackageFormatImport Path
yamlYAMLrivaas.dev/binding/yaml
tomlTOMLrivaas.dev/binding/toml
msgpackMessagePackrivaas.dev/binding/msgpack
protoProtocol Buffersrivaas.dev/binding/proto

Performance Characteristics

  • First binding: ~500ns overhead for reflection
  • Subsequent bindings: ~50ns overhead (cache lookup)
  • Query/Path/Form: Zero allocations for primitive types
  • JSON/XML: Allocations depend on encoding/json and encoding/xml
  • Thread-safe: All operations are safe for concurrent use

Integration

With net/http

func Handler(w http.ResponseWriter, r *http.Request) {
    req, err := binding.JSON[CreateUserRequest](r.Body)
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    // Process request...
}

With rivaas.dev/router

import "rivaas.dev/router"

func Handler(c *router.Context) error {
    req, err := binding.JSON[CreateUserRequest](c.Request().Body)
    if err != nil {
        return c.JSON(http.StatusBadRequest, err)
    }
    return c.JSON(http.StatusOK, processRequest(req))
}

With rivaas.dev/app

import "rivaas.dev/app"

func Handler(c *app.Context) error {
    var req CreateUserRequest
    if err := c.Bind(&req); err != nil {
        return err  // Automatically handled
    }
    return c.JSON(http.StatusOK, processRequest(req))
}

Version Compatibility

The binding package follows semantic versioning:

  • v1.x: Stable API, backward compatible
  • v2.x: Major changes, may require code updates

See Also


For step-by-step guides and tutorials, see the Binding Guide.

For real-world examples, see the Examples page.


API Reference

Complete API documentation for all types, functions, and interfaces

Options

Complete reference for all configuration options

Sub-Packages

YAML, TOML, MessagePack, and Protocol Buffers support

Troubleshooting

Common issues, solutions, and FAQs