edict

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: MIT Imports: 9 Imported by: 0

README

Edict

Go Reference CI Go Version

Edict is a zero-dependency validation library for Go. Declare rules with a fluent builder API, execute them in a single Validate() call, and get structured errors back. Because every field value is registered before any rule runs, cross-field comparisons and conditional requirements work without special wiring. Works with maps, structs, and direct values.

Features

Three data modes

  • Map mode: pass a map[string]any from your YAML/JSON parser, validate with dot-path field lookups
  • Struct mode: resolve values from exported struct fields via reflection
  • Direct-value mode: provide values explicitly per field

30+ built-in rules

  • Presence: Required, OneOf, NotOneOf
  • Numeric: IntRange, IntMin, IntMax, FloatRange, FloatMin, FloatMax, Max with automatic type coercion across int/float/json.Number variants
  • String length: MinLength, MaxLength, LenRange, LenExact (Unicode aware)
  • Format validators: IsEmail, IsURL, IsUUID, IsSlug, IsSemver, IsHexColor, IsAlpha, IsAlphaNumeric, IsNumeric, IsIPv4, IsIPv6

Cross-field rules

  • Comparison: LessOrEqual, EqField, GteField, LteField (numeric via float64, string fallback)
  • Conditional required: RequiredIf, RequiredUnless, RequiredWith, RequiredWithAll, RequiredWithout, RequiredWithoutAll
  • Exclusion: ExcludedIf, ExcludedUnless

Collection validation

  • Dive into slices, arrays, and maps with Each(), EachKey(), EachValue()
  • Wildcard paths: v.Field("servers.*.port") validates a sub-field across all elements
  • Distinct() for duplicate detection
  • Nested dives for multidimensional collections

Error model

  • Errors and warnings as separate concerns with per-rule severity
  • Structured access: Path, Code, Value, Message, Severity
  • Deterministic output in field declaration order
  • Internal errors for infrastructure failures in custom rules

Extensibility

  • Rule interface, RuleFunc, Check(), CheckIf()
  • ResolverAware for custom cross-field rules
  • RuleGroup for reusable rule sets
  • WithMessages registry for i18n

Install

go get github.com/frostybee/edict

Requires Go 1.25+.

Quick start

Map mode

Ideal for YAML/JSON config data parsed into map[string]any. Supports nested maps via dot-path traversal.

data := map[string]any{
    "port":   99999,
    "format": "xml",
}

v := edict.FromMap(data)
v.Field("port").Required().IntRange(1, 65535)
v.Field("format").OneOf("json", "csv", "table")

if err := v.Validate(); err != nil {
    fmt.Println(err)
    // port: must be between 1 and 65535 (got 99999)
    // format: must be one of: json, csv, table (got "xml")
}

Direct-value mode

The caller provides values explicitly. Useful when validating struct fields or standalone variables.

v := edict.New()
v.Field("port").Value(cfg.Port).Required().IntRange(1, 65535)
v.Field("title").Value(cfg.Title).Required()

if err := v.Validate(); err != nil {
    fmt.Println(err)
}

Struct mode

Values resolved from exported struct fields via reflection. Paths use Go field names, not struct tags.

v := edict.FromStruct(&cfg)
v.Field("Port").Required().IntRange(1, 65535)
v.Field("DarkMode.Kind").OneOf("selector", "mediaQuery")

if err := v.Validate(); err != nil {
    fmt.Println(err)
}

All three modes share the same rules and produce identical output. Cross-field rules work in every mode.

A real-world example

Validating a static site generator config with hard errors and soft warnings:

func Validate(cfg *SiteConfig) ([]edict.Error, error) {
    v := edict.New()

    v.Field("site.title").Value(cfg.Site.Title).Required()
    v.Field("site.language").Value(cfg.Site.Language).Required()
    v.Field("server.port").Value(cfg.Server.Port).IntRange(1, 65535)
    v.Field("toc.min_level").Value(cfg.TOC.MinLevel).IntRange(1, 6)
    v.Field("toc.max_level").Value(cfg.TOC.MaxLevel).IntRange(1, 6)
    v.Field("toc.min_level").LessOrEqual("toc.max_level")
    v.Field("deploy.provider").Value(cfg.Deploy.Provider).
        OneOf("netlify", "vercel", "cloudflare", "github-pages")

    v.Warn("site.url").Value(cfg.Site.URL).Required()
    v.Warn("site.description").Value(cfg.Site.Description).Required()

    err := v.Validate()
    return v.Warnings(), err
}

Configuration

Validator options

Pass options when creating a validator:

v := edict.FromMap(data, edict.StopOnFirst(), edict.StrictFields())
Option Effect
StopOnFirst() Stop after the first error (warnings don't trigger the stop)
StrictFields(known...) Report unknown keys as errors. No args = auto-detect from declared fields
WithMessages(registry) Register global message overrides by rule code (i18n)

Field filtering

Restrict which fields are validated. Excluded fields still contribute values for cross-field rule lookups.

v.Only("port", "format")           // validate only these fields
v.Except("deprecated_field")       // skip this field

Modifiers

Chain after any rule to change its behavior:

v.Field("port").IntMin(1024).AsWarning()
v.Field("format").OneOf("json", "csv").Message("unsupported output format")
Modifier Effect
AsWarning() Changes severity of the last rule to warning
Message(msg) Overrides the error message of the last rule
OmitEmpty() Skips rules when value is zero (default behavior, makes intent explicit)
OmitNil() Skips rules only when value is nil; zero values like 0, "", false still validate

Severity

Rules default to SeverityError. Use v.Warn("path") to start a chain where all rules default to SeverityWarning, or .AsWarning() to change just the last added rule.

Error handling

Validate() returns nil on success. On failure, it returns a *Results that implements error:

var results *edict.Results
if errors.As(err, &results) {
    for _, e := range results.Errors() {
        fmt.Printf("field=%s code=%s msg=%s\n", e.Path, e.Code, e.Message)
    }
}

Warnings never affect the error return. Access them via v.Warnings() after calling Validate().

Message registry

Override error messages globally by rule code. Per-field .Message() overrides take precedence.

v := edict.FromMap(data, edict.WithMessages(edict.MessageRegistry{
    "required": func(e edict.Error) string {
        return fmt.Sprintf("%s is a required field", e.Path)
    },
}))

Development

go build ./...
go test ./...
go test -run TestSpecificName ./...
go vet ./...

No Makefile, no task runner. Standard Go toolchain only.

Contributing

  1. Fork and create a feature branch.
  2. Run go test ./... before submitting.
  3. Keep changes focused. One feature or fix per PR.

When adding a new rule, include thorough tests covering: boundary values, zero-value types (nil, "", 0, false), wrong types, error message content, and error code assertions. See existing rules_*_test.go files for the expected depth.

License

Copyright (c) 2026 FrostyBee.

Edict is licensed under the MIT License.


Full API documentation: pkg.go.dev/github.com/frostybee/edict

Documentation

Overview

Package edict provides a fluent, type-safe API for validating maps, structs, and direct values with zero external dependencies.

Three data modes are supported:

// Map mode: values looked up by dot-path
v := edict.FromMap(data)
v.Field("port").Required().IntRange(1, 65535)
v.Field("darkMode.kind").OneOf("selector", "mediaQuery", "both")
if err := v.Validate(); err != nil {
    fmt.Println(err)
}

// Direct-value mode: caller provides values explicitly
v := edict.New()
v.Field("port").Value(cfg.Port).Required().IntRange(1, 65535)
if err := v.Validate(); err != nil {
    fmt.Println(err)
}

// Struct mode: values resolved from exported struct fields
v := edict.FromStruct(&cfg)
v.Field("Port").Required().IntRange(1, 65535)
v.Field("DarkMode.Kind").OneOf("selector", "mediaQuery")
if err := v.Validate(); err != nil {
    fmt.Println(err)
}

Rules are declared first, then executed in a single Validate() call. Cross-field rules work identically across all three data modes.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FormatErrors

func FormatErrors(errs []Error) string

FormatErrors formats a slice of Error values as a multi-line string.

Types

type Coder

type Coder interface {
	Code() string
}

Coder is optionally implemented by rules that provide a stable error code.

type DiveBuilder

type DiveBuilder struct {
	// contains filtered or unexported fields
}

DiveBuilder provides a fluent API for declaring rules on collection elements.

func (*DiveBuilder) Apply

func (db *DiveBuilder) Apply(rules ...Rule) *DiveBuilder

Apply adds custom Rule implementations to validate each element.

func (*DiveBuilder) Check

func (db *DiveBuilder) Check(fn func(value any) bool, msg string) *DiveBuilder

Check validates each element with a custom function.

func (*DiveBuilder) CheckIf

func (db *DiveBuilder) CheckIf(cond bool, msg string) *DiveBuilder

CheckIf adds a pre-evaluated boolean condition to each element.

func (*DiveBuilder) Each

func (db *DiveBuilder) Each() *DiveBuilder

Each creates a nested dive for multidimensional collections.

func (*DiveBuilder) End

func (db *DiveBuilder) End() *FieldBuilder

End returns the parent FieldBuilder to resume the field chain.

func (*DiveBuilder) FloatMax

func (db *DiveBuilder) FloatMax(max float64) *DiveBuilder

FloatMax validates that each element is <= max.

func (*DiveBuilder) FloatMin

func (db *DiveBuilder) FloatMin(min float64) *DiveBuilder

FloatMin validates that each element is >= min.

func (*DiveBuilder) FloatRange

func (db *DiveBuilder) FloatRange(min, max float64) *DiveBuilder

FloatRange validates that each element is in [min, max].

func (*DiveBuilder) IntMax

func (db *DiveBuilder) IntMax(max int) *DiveBuilder

IntMax validates that each element is <= max.

func (*DiveBuilder) IntMin

func (db *DiveBuilder) IntMin(min int) *DiveBuilder

IntMin validates that each element is >= min.

func (*DiveBuilder) IntRange

func (db *DiveBuilder) IntRange(min, max int) *DiveBuilder

IntRange validates that each element is in [min, max].

func (*DiveBuilder) LenExact

func (db *DiveBuilder) LenExact(n int) *DiveBuilder

LenExact checks that each string element has exactly n characters.

func (*DiveBuilder) LenRange

func (db *DiveBuilder) LenRange(min, max int) *DiveBuilder

LenRange checks that each string element length is in [min, max].

func (*DiveBuilder) Max

func (db *DiveBuilder) Max(max float64) *DiveBuilder

Max validates that each element is <= max (any numeric type).

func (*DiveBuilder) MaxLength

func (db *DiveBuilder) MaxLength(n int) *DiveBuilder

MaxLength checks that each string element has at most n characters.

func (*DiveBuilder) MinLength

func (db *DiveBuilder) MinLength(n int) *DiveBuilder

MinLength checks that each string element has at least n characters.

func (*DiveBuilder) NotOneOf

func (db *DiveBuilder) NotOneOf(forbidden ...string) *DiveBuilder

NotOneOf validates that each element is NOT in the forbidden set.

func (*DiveBuilder) OneOf

func (db *DiveBuilder) OneOf(allowed ...string) *DiveBuilder

OneOf validates that each element is one of the allowed strings.

func (*DiveBuilder) Required

func (db *DiveBuilder) Required() *DiveBuilder

Required validates that each element is non-zero.

type Error

type Error struct {
	Path     string
	Code     string
	Value    string
	Message  string
	Severity Severity
}

func (Error) Error

func (e Error) Error() string

type FieldBuilder

type FieldBuilder struct {
	// contains filtered or unexported fields
}

FieldBuilder provides the fluent API for declaring rules on a single field.

func (*FieldBuilder) Apply

func (fb *FieldBuilder) Apply(rules ...Rule) *FieldBuilder

Apply adds one or more custom Rule implementations to this field.

func (*FieldBuilder) AsWarning

func (fb *FieldBuilder) AsWarning() *FieldBuilder

AsWarning sets the severity of the last added rule to Warning.

func (*FieldBuilder) Check

func (fb *FieldBuilder) Check(fn func(value any) bool, msg string) *FieldBuilder

Check applies a custom function condition.

func (*FieldBuilder) CheckIf

func (fb *FieldBuilder) CheckIf(cond bool, msg string) *FieldBuilder

CheckIf applies a pre-evaluated boolean condition.

func (*FieldBuilder) Distinct

func (fb *FieldBuilder) Distinct() *FieldBuilder

Distinct checks that a slice or array contains no duplicate elements.

func (*FieldBuilder) Each

func (fb *FieldBuilder) Each() *DiveBuilder

Each creates a DiveBuilder that validates each element of a slice or array.

func (*FieldBuilder) EachKey

func (fb *FieldBuilder) EachKey() *DiveBuilder

EachKey creates a DiveBuilder that validates each key of a map.

func (*FieldBuilder) EachValue

func (fb *FieldBuilder) EachValue() *DiveBuilder

EachValue creates a DiveBuilder that validates each value of a map.

func (*FieldBuilder) EqField

func (fb *FieldBuilder) EqField(other string) *FieldBuilder

EqField checks that this field's value equals another field's value.

func (*FieldBuilder) ExcludedIf

func (fb *FieldBuilder) ExcludedIf(field string, values ...string) *FieldBuilder

ExcludedIf fails if this field is non-zero and the other field matches any of the given values.

func (*FieldBuilder) ExcludedUnless

func (fb *FieldBuilder) ExcludedUnless(field string, values ...string) *FieldBuilder

ExcludedUnless fails if this field is non-zero and the other field does NOT match any of the given values.

func (*FieldBuilder) FloatMax

func (fb *FieldBuilder) FloatMax(max float64) *FieldBuilder

FloatMax checks that a float64 value is <= max.

func (*FieldBuilder) FloatMin

func (fb *FieldBuilder) FloatMin(min float64) *FieldBuilder

FloatMin checks that a float64 value is >= min.

func (*FieldBuilder) FloatRange

func (fb *FieldBuilder) FloatRange(min, max float64) *FieldBuilder

FloatRange checks that a float64 value is in [min, max].

func (*FieldBuilder) GteField

func (fb *FieldBuilder) GteField(other string) *FieldBuilder

GteField checks that this field's value is >= another field's value.

func (*FieldBuilder) IntMax

func (fb *FieldBuilder) IntMax(max int) *FieldBuilder

IntMax checks that an int value is <= max.

func (*FieldBuilder) IntMin

func (fb *FieldBuilder) IntMin(min int) *FieldBuilder

IntMin checks that an int value is >= min.

func (*FieldBuilder) IntRange

func (fb *FieldBuilder) IntRange(min, max int) *FieldBuilder

IntRange checks that an int value is in [min, max].

func (*FieldBuilder) IsAlpha

func (fb *FieldBuilder) IsAlpha() *FieldBuilder

IsAlpha validates that the value contains only ASCII letters.

func (*FieldBuilder) IsAlphaNumeric

func (fb *FieldBuilder) IsAlphaNumeric() *FieldBuilder

IsAlphaNumeric validates that the value contains only ASCII letters and digits.

func (*FieldBuilder) IsEmail

func (fb *FieldBuilder) IsEmail() *FieldBuilder

IsEmail validates that the value is a valid email address.

func (*FieldBuilder) IsHexColor

func (fb *FieldBuilder) IsHexColor() *FieldBuilder

IsHexColor validates hex color format (#RGB or #RRGGBB).

func (*FieldBuilder) IsIPv4

func (fb *FieldBuilder) IsIPv4() *FieldBuilder

IsIPv4 validates IPv4 address format.

func (*FieldBuilder) IsIPv6

func (fb *FieldBuilder) IsIPv6() *FieldBuilder

IsIPv6 validates IPv6 address format.

func (*FieldBuilder) IsNumeric

func (fb *FieldBuilder) IsNumeric() *FieldBuilder

IsNumeric validates that the value contains only ASCII digits.

func (*FieldBuilder) IsSemver

func (fb *FieldBuilder) IsSemver() *FieldBuilder

IsSemver validates semantic versioning format (X.Y.Z with optional v prefix).

func (*FieldBuilder) IsSlug

func (fb *FieldBuilder) IsSlug() *FieldBuilder

IsSlug validates that the value is a valid URL slug (lowercase alphanumeric with hyphens).

func (*FieldBuilder) IsURL

func (fb *FieldBuilder) IsURL() *FieldBuilder

IsURL validates URL format (requires http/https scheme and host).

func (*FieldBuilder) IsUUID

func (fb *FieldBuilder) IsUUID() *FieldBuilder

IsUUID validates that the value is a valid UUID (8-4-4-4-12 hex).

func (*FieldBuilder) LenExact

func (fb *FieldBuilder) LenExact(n int) *FieldBuilder

LenExact checks that a string value has exactly n characters.

func (*FieldBuilder) LenRange

func (fb *FieldBuilder) LenRange(min, max int) *FieldBuilder

LenRange checks that a string value length is in [min, max].

func (*FieldBuilder) LessOrEqual

func (fb *FieldBuilder) LessOrEqual(otherField string) *FieldBuilder

LessOrEqual checks that this field's int value <= another field's int value.

func (*FieldBuilder) LteField

func (fb *FieldBuilder) LteField(other string) *FieldBuilder

LteField checks that this field's value is <= another field's value.

func (*FieldBuilder) Max

func (fb *FieldBuilder) Max(max float64) *FieldBuilder

Max checks that a numeric value is <= max (any numeric type via float64 coercion).

func (*FieldBuilder) MaxLength

func (fb *FieldBuilder) MaxLength(n int) *FieldBuilder

MaxLength checks that a string value has at most n characters.

func (*FieldBuilder) Message

func (fb *FieldBuilder) Message(msg string) *FieldBuilder

Message overrides the error message of the last added rule.

func (*FieldBuilder) MinLength

func (fb *FieldBuilder) MinLength(n int) *FieldBuilder

MinLength checks that a string value has at least n characters.

func (*FieldBuilder) NotOneOf

func (fb *FieldBuilder) NotOneOf(forbidden ...string) *FieldBuilder

NotOneOf checks that a string value is NOT in the forbidden set.

func (*FieldBuilder) OmitEmpty

func (fb *FieldBuilder) OmitEmpty() *FieldBuilder

OmitEmpty skips rule evaluation when the value is a zero value. This matches the default behavior but makes the intent explicit. Panics if called after Required(), since the two are contradictory.

func (*FieldBuilder) OmitNil

func (fb *FieldBuilder) OmitNil() *FieldBuilder

OmitNil skips rule evaluation only when the value is nil. Non-nil zero values (0, "", false) are not skipped. Panics if called after Required(), since the two are contradictory.

func (*FieldBuilder) OneOf

func (fb *FieldBuilder) OneOf(allowed ...string) *FieldBuilder

OneOf checks that a string value is one of the allowed values.

func (*FieldBuilder) Required

func (fb *FieldBuilder) Required() *FieldBuilder

Required marks the field as required.

func (*FieldBuilder) RequiredIf

func (fb *FieldBuilder) RequiredIf(field string, values ...string) *FieldBuilder

RequiredIf makes this field required when another field matches any of the given values.

func (*FieldBuilder) RequiredUnless

func (fb *FieldBuilder) RequiredUnless(field string, values ...string) *FieldBuilder

RequiredUnless makes this field required unless another field matches any of the given values.

func (*FieldBuilder) RequiredWith

func (fb *FieldBuilder) RequiredWith(fields ...string) *FieldBuilder

RequiredWith makes this field required when any of the listed fields are present and non-zero.

func (*FieldBuilder) RequiredWithAll

func (fb *FieldBuilder) RequiredWithAll(fields ...string) *FieldBuilder

RequiredWithAll makes this field required when all of the listed fields are present and non-zero.

func (*FieldBuilder) RequiredWithout

func (fb *FieldBuilder) RequiredWithout(fields ...string) *FieldBuilder

RequiredWithout makes this field required when any of the listed fields are absent or zero.

func (*FieldBuilder) RequiredWithoutAll

func (fb *FieldBuilder) RequiredWithoutAll(fields ...string) *FieldBuilder

RequiredWithoutAll makes this field required when all of the listed fields are absent or zero.

func (*FieldBuilder) Value

func (fb *FieldBuilder) Value(v any) *FieldBuilder

Value provides a direct value for this field.

func (*FieldBuilder) When

func (fb *FieldBuilder) When(cond bool, rules ...Rule) *FieldBuilder

When wraps the given rules in a conditional guard.

type InternalError

type InternalError struct {
	Err error
}

InternalError signals an infrastructure failure inside a custom rule (e.g., database down, file not found). Internal errors are collected separately from validation errors and never block Validate().

func (*InternalError) Error

func (e *InternalError) Error() string

func (*InternalError) Unwrap

func (e *InternalError) Unwrap() error

type MessageFunc

type MessageFunc func(e Error) string

MessageFunc formats a custom message given the validation error context.

type MessageRegistry

type MessageRegistry map[string]MessageFunc

MessageRegistry maps rule codes to custom message functions. When a rule produces an error whose Code matches a registry key, the registry function is called and its return value replaces the message.

type Option

type Option func(*validatorOptions)

Option configures a Validator.

func StopOnFirst

func StopOnFirst() Option

StopOnFirst returns an Option that causes Validate() to return after the first validation error. Warnings do not trigger the stop.

func StrictFields

func StrictFields(known ...string) Option

StrictFields returns an Option that reports any key present in the data source but not in the known set as an unknown_field error.

When called with no arguments, the known set is built from the field paths declared on the validator via Field() and Warn() calls. When called with explicit paths, those paths are used instead.

func WithMessages

func WithMessages(registry MessageRegistry) Option

WithMessages returns an Option that registers custom message overrides. Registry messages are only applied when no per-field .Message() override is set. Precedence: .Message() > registry > rule default.

type ResolverAware

type ResolverAware interface {
	Bind(r ValueResolver)
}

ResolverAware is implemented by rules that need to look up other field values. The Validator calls Bind() before Validate() during the execution phase.

type Results

type Results struct {
	// contains filtered or unexported fields
}

func (*Results) AllIssues

func (r *Results) AllIssues() []Error

func (*Results) Error

func (r *Results) Error() string

func (*Results) Errors

func (r *Results) Errors() []Error

func (*Results) FormatErrors

func (r *Results) FormatErrors() string

func (*Results) FormatWarnings

func (r *Results) FormatWarnings() string

func (*Results) HasErrors

func (r *Results) HasErrors() bool

func (*Results) HasInternalErrors

func (r *Results) HasInternalErrors() bool

func (*Results) HasWarnings

func (r *Results) HasWarnings() bool

func (*Results) InternalErrors

func (r *Results) InternalErrors() []error

func (*Results) Warnings

func (r *Results) Warnings() []Error

type Rule

type Rule interface {
	Validate(value any) error
}

Rule validates a single value and returns nil on success or an error on failure. Rules must be safe for reuse across multiple Validate() calls.

func NewCheck

func NewCheck(fn func(value any) bool, msg string) Rule

NewCheck returns a Rule that fails when fn returns false for the field value.

func NewCheckIf

func NewCheckIf(cond bool, msg string) Rule

NewCheckIf returns a Rule that fails when cond is false.

func NewDistinct

func NewDistinct() Rule

NewDistinct returns a Rule that fails when a slice or array contains duplicate elements.

func NewEqField

func NewEqField(other string) Rule

NewEqField returns a Rule that fails when this field's value does not equal another field's value.

func NewExcludedIf

func NewExcludedIf(field string, values ...string) Rule

NewExcludedIf returns a Rule that fails when this field is non-zero and another field matches any of the given values.

func NewExcludedUnless

func NewExcludedUnless(field string, values ...string) Rule

NewExcludedUnless returns a Rule that fails when this field is non-zero and another field does NOT match any of the given values.

func NewFloatMax

func NewFloatMax(max float64) Rule

NewFloatMax returns a Rule that fails when the float value exceeds max.

func NewFloatMin

func NewFloatMin(min float64) Rule

NewFloatMin returns a Rule that fails when the float value is below min.

func NewFloatRange

func NewFloatRange(min, max float64) Rule

NewFloatRange returns a Rule that fails when the float value is outside [min, max].

func NewGteField

func NewGteField(other string) Rule

NewGteField returns a Rule that fails when this field's value is less than another field's value.

func NewIntMax

func NewIntMax(max int) Rule

NewIntMax returns a Rule that fails when the integer value exceeds max.

func NewIntMin

func NewIntMin(min int) Rule

NewIntMin returns a Rule that fails when the integer value is below min.

func NewIntRange

func NewIntRange(min, max int) Rule

NewIntRange returns a Rule that fails when the integer value is outside [min, max].

func NewLenExact

func NewLenExact(n int) Rule

NewLenExact returns a Rule that fails when the string is not exactly n characters.

func NewLenRange

func NewLenRange(min, max int) Rule

NewLenRange returns a Rule that fails when the string length is outside [min, max].

func NewLessOrEqual

func NewLessOrEqual(otherPath string) Rule

NewLessOrEqual returns a Rule that fails when this field's value exceeds another field's value.

func NewLteField

func NewLteField(other string) Rule

NewLteField returns a Rule that fails when this field's value is greater than another field's value.

func NewMax

func NewMax(max float64) Rule

NewMax returns a Rule that fails when any numeric value exceeds max.

func NewMaxLength

func NewMaxLength(n int) Rule

NewMaxLength returns a Rule that fails when the string is longer than n characters.

func NewMinLength

func NewMinLength(n int) Rule

NewMinLength returns a Rule that fails when the string is shorter than n characters.

func NewNotOneOf

func NewNotOneOf(forbidden ...string) Rule

NewNotOneOf returns a Rule that fails when the string value IS in the forbidden set.

func NewOneOf

func NewOneOf(allowed ...string) Rule

NewOneOf returns a Rule that fails when the string value is not in the allowed set.

func NewRequired

func NewRequired() Rule

NewRequired returns a Rule that fails when the value is zero.

func NewRequiredIf

func NewRequiredIf(field string, values ...string) Rule

NewRequiredIf returns a Rule that makes a field required when another field matches any of the given values.

func NewRequiredUnless

func NewRequiredUnless(field string, values ...string) Rule

NewRequiredUnless returns a Rule that makes a field required unless another field matches any of the given values.

func NewRequiredWith

func NewRequiredWith(fields ...string) Rule

NewRequiredWith returns a Rule that makes a field required when any of the listed fields are present and non-zero.

func NewRequiredWithAll

func NewRequiredWithAll(fields ...string) Rule

NewRequiredWithAll returns a Rule that makes a field required when all of the listed fields are present and non-zero.

func NewRequiredWithout

func NewRequiredWithout(fields ...string) Rule

NewRequiredWithout returns a Rule that makes a field required when any of the listed fields are absent or zero.

func NewRequiredWithoutAll

func NewRequiredWithoutAll(fields ...string) Rule

NewRequiredWithoutAll returns a Rule that makes a field required when all of the listed fields are absent or zero.

func NewWhen

func NewWhen(cond bool, rules ...Rule) Rule

NewWhen returns a Rule that runs the given rules only when cond is true.

type RuleFunc

type RuleFunc func(value any) error

RuleFunc adapts a function to the Rule interface.

func (RuleFunc) Validate

func (f RuleFunc) Validate(value any) error

type RuleGroup

type RuleGroup struct {
	// contains filtered or unexported fields
}

RuleGroup holds a reusable set of rules that can be applied to multiple fields.

func (*RuleGroup) Rules

func (g *RuleGroup) Rules() []Rule

Rules returns the rules in the group.

type RuleGroupBuilder

type RuleGroupBuilder struct {
	// contains filtered or unexported fields
}

RuleGroupBuilder constructs a RuleGroup via a fluent API.

func NewRuleGroup

func NewRuleGroup() *RuleGroupBuilder

NewRuleGroup starts building a reusable rule group.

func (*RuleGroupBuilder) Build

func (b *RuleGroupBuilder) Build() *RuleGroup

Build finalizes the group and returns an immutable RuleGroup.

func (*RuleGroupBuilder) FloatMax

func (b *RuleGroupBuilder) FloatMax(max float64) *RuleGroupBuilder

func (*RuleGroupBuilder) FloatMin

func (b *RuleGroupBuilder) FloatMin(min float64) *RuleGroupBuilder

func (*RuleGroupBuilder) FloatRange

func (b *RuleGroupBuilder) FloatRange(min, max float64) *RuleGroupBuilder

func (*RuleGroupBuilder) IntMax

func (b *RuleGroupBuilder) IntMax(max int) *RuleGroupBuilder

func (*RuleGroupBuilder) IntMin

func (b *RuleGroupBuilder) IntMin(min int) *RuleGroupBuilder

func (*RuleGroupBuilder) IntRange

func (b *RuleGroupBuilder) IntRange(min, max int) *RuleGroupBuilder

func (*RuleGroupBuilder) LenExact

func (b *RuleGroupBuilder) LenExact(n int) *RuleGroupBuilder

func (*RuleGroupBuilder) LenRange

func (b *RuleGroupBuilder) LenRange(min, max int) *RuleGroupBuilder

func (*RuleGroupBuilder) Max

func (*RuleGroupBuilder) MaxLength

func (b *RuleGroupBuilder) MaxLength(n int) *RuleGroupBuilder

func (*RuleGroupBuilder) MinLength

func (b *RuleGroupBuilder) MinLength(n int) *RuleGroupBuilder

func (*RuleGroupBuilder) NotOneOf

func (b *RuleGroupBuilder) NotOneOf(forbidden ...string) *RuleGroupBuilder

func (*RuleGroupBuilder) OneOf

func (b *RuleGroupBuilder) OneOf(allowed ...string) *RuleGroupBuilder

func (*RuleGroupBuilder) Required

func (b *RuleGroupBuilder) Required() *RuleGroupBuilder

type Severity

type Severity int
const (
	SeverityError Severity = iota
	SeverityWarning
)

type Validator

type Validator struct {
	// contains filtered or unexported fields
}

Validator accumulates field rules and executes them in a single Validate() call.

func FromMap

func FromMap(data map[string]any, opts ...Option) *Validator

FromMap creates a Validator backed by a map. Supports nested maps via dot-path traversal.

func FromStruct

func FromStruct(target any, opts ...Option) *Validator

FromStruct creates a Validator backed by a struct. Fields are resolved by exported field names using dot-path traversal.

func New

func New(opts ...Option) *Validator

New creates a Validator with no data source. Fields must provide values via .Value() on the FieldBuilder.

func (*Validator) Except

func (v *Validator) Except(paths ...string) *Validator

Except skips validation for the given field paths. All other fields run normally. Excluded fields still contribute values for cross-field rule lookups.

func (*Validator) Field

func (v *Validator) Field(path string) *FieldBuilder

Field starts a fluent rule chain for the given field path. Rules appended via Field() default to SeverityError.

func (*Validator) HasInternalErrors

func (v *Validator) HasInternalErrors() bool

HasInternalErrors returns true if the last Validate() call produced internal errors.

func (*Validator) InternalErrors

func (v *Validator) InternalErrors() []error

InternalErrors returns internal errors from the last Validate() call.

func (*Validator) Only

func (v *Validator) Only(paths ...string) *Validator

Only restricts validation to the given field paths. All other fields are skipped. Excluded fields still contribute values for cross-field rule lookups.

func (*Validator) Validate

func (v *Validator) Validate() error

Validate runs all accumulated rules and returns an error if any validation errors exist. Returns nil if there are no errors.

func (*Validator) Warn

func (v *Validator) Warn(path string) *FieldBuilder

Warn starts a fluent rule chain identical to Field(), but rules appended via Warn() default to SeverityWarning.

func (*Validator) Warnings

func (v *Validator) Warnings() []Error

Warnings returns warnings from the last Validate() call.

type ValueResolver

type ValueResolver interface {
	Resolve(path string) (value any, found bool)
	Keys() []string
}

ValueResolver looks up field values by dotted path.

Directories

Path Synopsis
internal
Package is provides format validation rules for common string patterns.
Package is provides format validation rules for common string patterns.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL