golazy.dev golazy.dev / lazyschema Index | Files

package lazyschema

import "golazy.dev/lazyschema"

Package lazyschema fills structs from form values and generates the field names used by GoLazy forms.

The package is adapted from Gorilla schema. It keeps Gorilla's reflection-based decoder model, converters, required/default tag options, and slice protection, but GoLazy owns the generated key format.

The default field key is lower-camel per Go field segment, with underscores for nested paths:

type Person struct {
	Name  string
	Phone Phone
}

type Phone struct {
	Label  string
	Number string
}

values := map[string][]string{
	"name":         {"Ada"},
	"phone_label":  {"mobile"},
	"phone_number": {"555-0100"},
}

var person Person
decoder := lazyschema.NewDecoder()
err := decoder.Decode(&person, values)

Slices of structs include explicit numeric indexes:

type Person struct {
	Phones []Phone
}

values := map[string][]string{
	"phones_0_label":  {"home"},
	"phones_0_number": {"555-0100"},
	"phones_1_label":  {"work"},
	"phones_1_number": {"555-0101"},
}

Use the "schema" struct tag to override names or ignore fields:

type Person struct {
	Name  string `schema:"fullName"`
	Admin bool   `schema:"-"`
}

The same package generates field names and ids, so form helpers and decoding stay aligned:

name, _ := lazyschema.FieldNameFor(Person{}, "Phone.Number")
id, _ := lazyschema.FieldIDFor(Person{}, "Phone.Number", lazyschema.WithPrefix("person"))

The supported field types match Gorilla schema's core types: bools, strings, integers, floats, structs, pointers to supported types, and slices. Custom types can be registered with RegisterConverter. time.Time is registered by default for common HTML date, time, and datetime input values.

Functions

func FieldIDFor

FieldIDFor returns the generated DOM id for a Go field path.

func FieldIDFor(model any, field string, opts ...NameOption) (string, error)

func FieldNameFor

FieldNameFor returns the generated form field name for a Go field path.

func FieldNameFor(model any, field string, opts ...NameOption) (string, error)

func FormatTime

FormatTime formats a time value for HTML date and time inputs.

func FormatTime(t time.Time, inputType string) string

func ModelName

ModelName returns the default lower-camel key for a model value or type.

func ModelName(model any) (string, error)

func ModelNameForType

ModelNameForType returns the default lower-camel key for a struct type.

func ModelNameForType(t reflect.Type) (string, error)

Types

type ConversionError

ConversionError stores information about a failed conversion.

type ConversionError struct {
	Key	string		// key from the source map.
	Type	reflect.Type	// expected type of elem
	Index	int		// index for multi-value fields; -1 for single-value fields.
	Err	error		// low-level error (when it exists)
}
func (e ConversionError) Error
func (e ConversionError) Error() string

type Decoder

Decoder decodes values from a map[string][]string to a struct.

type Decoder struct {
	// contains filtered or unexported fields
}
func NewDecoder

NewDecoder returns a new Decoder.

func NewDecoder() *Decoder
func (d *Decoder) Decode

Decode decodes a map[string][]string to a struct.

The first parameter must be a pointer to a struct.

The second parameter is a map, typically url.Values from an HTTP request. Keys are "paths" in dotted notation to the struct fields and nested structs.

See the package documentation for a full explanation of the mechanics.

func (d *Decoder) Decode(dst interface{}, src map[string][]string) error
func (d *Decoder) IgnoreUnknownKeys

IgnoreUnknownKeys controls the behaviour when the decoder encounters unknown keys in the map. If i is true and an unknown field is encountered, it is ignored. This is similar to how unknown keys are handled by encoding/json. If i is false then Decode will return an error. Note that any valid keys will still be decoded in to the target struct.

To preserve backwards compatibility, the default value is false.

func (d *Decoder) IgnoreUnknownKeys(i bool)
func (d *Decoder) MaxDepth

MaxDepth limits the number of nested path segments in each submitted key.

func (d *Decoder) MaxDepth(size int)
func (d *Decoder) MaxKeyLength

MaxKeyLength limits the length of each submitted key.

func (d *Decoder) MaxKeyLength(size int)
func (d *Decoder) MaxKeys

MaxKeys limits how many distinct form keys one Decode call accepts.

func (d *Decoder) MaxKeys(size int)
func (d *Decoder) MaxSize

MaxSize limits the size of slices for URL nested arrays or object arrays. Choose MaxSize carefully; large values may create many zero-value slice elements. Example: "items.100000=apple" would create a slice with 100,000 empty strings.

func (d *Decoder) MaxSize(size int)
func (d *Decoder) MaxValuesPerKey

MaxValuesPerKey limits how many submitted values one key accepts.

func (d *Decoder) MaxValuesPerKey(size int)
func (d *Decoder) RegisterConverter

RegisterConverter registers a converter function for a custom type.

func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter)
func (d *Decoder) SetAliasTag

SetAliasTag changes the tag used to locate custom field aliases. The default tag is "schema".

func (d *Decoder) SetAliasTag(tag string)
func (d *Decoder) ZeroEmpty

ZeroEmpty controls the behaviour when the decoder encounters empty values in a map. If z is true and a key in the map has the empty string as a value then the corresponding struct field is set to the zero value. If z is false then empty strings are ignored.

The default value is false, that is empty values do not change the value of the struct field.

func (d *Decoder) ZeroEmpty(z bool)

type Encoder

Encoder encodes values from a struct into url.Values.

type Encoder struct {
	// contains filtered or unexported fields
}
func NewEncoder

NewEncoder returns a new Encoder with defaults.

func NewEncoder() *Encoder
func (e *Encoder) Encode

Encode encodes a struct into map[string][]string.

Intended for use with url.Values.

func (e *Encoder) Encode(src interface{}, dst map[string][]string) error
func (e *Encoder) RegisterEncoder

RegisterEncoder registers a converter for encoding a custom type.

func (e *Encoder) RegisterEncoder(value interface{}, encoder func(reflect.Value) string)
func (e *Encoder) SetAliasTag

SetAliasTag changes the tag used to locate custom field aliases. The default tag is "schema".

func (e *Encoder) SetAliasTag(tag string)

type NameOption

NameOption configures generated field names and ids.

type NameOption func(*nameOptions)
func WithPrefix

WithPrefix prefixes generated field ids with a model or form key.

func WithPrefix(prefix string) NameOption

type Path

Path is a schema field path made of generated field aliases and optional slice indices.

type Path []string
func PathFor

PathFor returns the generated schema path for a Go field path such as "Phone.Label" or "Phones.0.Number".

func PathFor(model any, field string) (Path, error)