validate

package module
v0.0.0-...-c2c690a Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2025 License: MIT Imports: 10 Imported by: 0

README

Golang validation library

Validate is a simple golang validation library that is focussed on simplicity and typed validators.

GoDev

Usage

See examples_test.go for usage.

Creating custom validators

A validator is a simple function that takes a value and returns an error if the value is invalid. If the error is a violation it should return a validate.Violation error. If the error is an exception that should be handled by the caller it should return a normal error.

// Returns an error if the number is not 42.
func Is42(x int) error {
    if x != 42 {
        return &validate.Violdation{ Code: "Is42" }
    }

    return nil
}

Documentation

Index

Examples

Constants

View Source
const (
	CodeUnknownField = "unknown.field"
	CodeNotFound     = "not.found"
	CodeRequired     = "required"
	CodeNotNil       = "not.nil"
	CodeNot          = "not"
	CodeEqual        = "equal"
	CodeOneOf        = "oneof"
	CodeNumberMin    = "min.number"
	CodeNumberMax    = "max.number"
	CodeStringMin    = "min.string"
	CodeStringMax    = "max.string"
	CodePrefix       = "prefix"
	CodeSuffix       = "suffix"
	CodeEmail        = "email"
	CodeRegex        = "regex"
	CodeLowercase    = "lowercase"
	CodeUppercase    = "uppercase"
	CodeIBAN         = "iban"
)

Variables

This section is empty.

Functions

func Email

func Email(value string) error

func Field

func Field[T any](fieldName string, value T, validators ...Validator[T]) error

Field will run the validators on the value and return the errors grouped by the field. If a violation returned a non Violation that is returned as exception error.

Example
package main

import (
	"fmt"

	"github.com/SLASH2NL/validate"
)

func main() {
	err := validate.Field("email", "test", validate.Email)
	printError(err)

}

func printError(err error) {
	if err == nil {
		return
	}

	errs := validate.Collect(err)
	for _, e := range errs {
		fmt.Println(e.Error())
	}
}
Output:

validation error for exact path: email, path: email, args: map[], violations: [violation code: email, args: map[]]

func Group

func Group(prefix string, err error) error

Group will prefix the exact path in the given error. This function accepts Error and Errors.

func IBAN

func IBAN(value string) error

func IsValidationError

func IsValidationError(err error) bool

IsValidationError returns true if the given error is of type Error or Errors or if it contains a wrapped Error or Errors.

func Join

func Join(errs ...error) error

Join the errors into a single slice and merge all errors with the same exact path. It wil only Join errors that are of the type Error or Errors.

Example
package main

import (
	"fmt"

	"github.com/SLASH2NL/validate"
)

func main() {
	err := validate.Join(
		validate.Field("email", "test", validate.Email),
		validate.Field("iban", "invalid", validate.IBAN),
	)
	printError(err)

}

func printError(err error) {
	if err == nil {
		return
	}

	errs := validate.Collect(err)
	for _, e := range errs {
		fmt.Println(e.Error())
	}
}
Output:

validation error for exact path: email, path: email, args: map[], violations: [violation code: email, args: map[]]
validation error for exact path: iban, path: iban, args: map[], violations: [violation code: iban, args: map[]]

func LastPathSegment

func LastPathSegment(s string) string

LastPathSegment will return the last segment of the given path. It assumes the path is separated by dots.

func Lowercase

func Lowercase(value string) error

func NotNil

func NotNil[T any](value T) error

NotNil will return an error if value is nil.

func ReplaceIfErr

func ReplaceIfErr(err error, newErr error) error

ReplaceIfErr will replace err with the given newErr if err is not nil. This is usefull for overriding a validation error with a custom error.

func Required

func Required[T comparable](value T) error

Required will validate that the value is not the zero value for the type.

func Uppercase

func Uppercase(value string) error

Types

type Args

type Args map[string]any

func Merge

func Merge(a Args, b Args) Args

Merge merges a and b into a new Args. If a key exists in both a and b, the value from b is used.

func (Args) Add

func (e Args) Add(key string, value any) Args

type Error

type Error struct {
	Path       string
	ExactPath  string
	Args       Args
	Violations []Violation
}

func Collect

func Collect(err error) []Error

Collect will collect the Errors from the given error.

Example
package main

import (
	"fmt"

	"github.com/SLASH2NL/validate"
)

func main() {
	err := validate.Join(
		validate.Field("email", "test", validate.Email),
		validate.Field("iban", "invalid", validate.IBAN),
	)

	errs := validate.Collect(err)
	fmt.Printf("Size is %d", len(errs))

}
Output:

Size is 2

func (Error) Error

func (e Error) Error() string

type Errors

type Errors []Error

func (Errors) Error

func (e Errors) Error() string

type MapValidator

type MapValidator[K comparable, V any] struct {
	// contains filtered or unexported fields
}

func Map

func Map[K comparable, V any](name string, value map[K]V) MapValidator[K, V]
Example
package main

import (
	"fmt"

	"github.com/SLASH2NL/validate"
)

func main() {
	data := map[string]string{
		"first":  "john deer",
		"second": "Deer John",
	}

	err := validate.Map("data", data).Values("name", validate.Lowercase)
	printError(err)

}

func printError(err error) {
	if err == nil {
		return
	}

	errs := validate.Collect(err)
	for _, e := range errs {
		fmt.Println(e.Error())
	}
}
Output:

validation error for exact path: data.second.name, path: data.name, args: map[key:second], violations: [violation code: lowercase, args: map[]]

func (MapValidator[K, V]) Key

func (v MapValidator[K, V]) Key(field string, key K, validators ...Validator[V]) error

Key runs the validators on the value of the key. If the key does not exist, it will return an unknown.field violation.

func (MapValidator[K, V]) Keys

func (v MapValidator[K, V]) Keys(field string, validators ...Validator[K]) error

Keys runs the validators on all keys.

func (MapValidator[K, V]) Values

func (v MapValidator[K, V]) Values(field string, validators ...Validator[V]) error

Values runs the validators on all values.

type SliceValidator

type SliceValidator[T any] struct {
	// contains filtered or unexported fields
}

func Slice

func Slice[F ~string, T any](name F, value []T) SliceValidator[T]

Slice will run the validators on each element in the slice.

Example
data := []testSlice{
	{Name: "John Deer", Amount: 9},
	{Name: "Deer John", Amount: 1},
}

err := validate.Slice("data", data).Items("total", validate.Resolve(func(value testSlice) int { return value.Amount }, validate.MaxNumber(5))...)
printError(err)
Output:

validation error for exact path: data.0.total, path: data.*.total, args: map[index:0], violations: [violation code: max.number, args: map[max:5]]

func (SliceValidator[T]) Items

func (v SliceValidator[T]) Items(field string, validators ...Validator[T]) error

type Validator

type Validator[T any] func(value T) error

Validator represents a validator that can be used to validate a value. If a validator fails it should return an new Violation. If there is an unexpected exception a normal error should be returned. This error will bubble up and be returned to the caller.

func And

func And[T any](validators ...Validator[T]) Validator[T]

And will run all validators and only return an error if all validators error.

func Equal

func Equal[T comparable](expected T) Validator[T]

Equal will validate that the value is equal to the expected value. This will not do a deep comparison.

func FailFirst

func FailFirst[T any](validators ...Validator[T]) Validator[T]

FailFirst will run the validators in order and return the first error.

Example
package main

import (
	"fmt"

	"github.com/SLASH2NL/validate"
)

func main() {
	err := validate.Field("email", "test", validate.FailFirst(validate.Email, validate.MinString(100)))
	printError(err)

}

func printError(err error) {
	if err == nil {
		return
	}

	errs := validate.Collect(err)
	for _, e := range errs {
		fmt.Println(e.Error())
	}
}
Output:

validation error for exact path: email, path: email, args: map[], violations: [violation code: email, args: map[]]

func If

func If[T any](shouldRun bool, validators ...Validator[T]) Validator[T]

If will run the validators only if the shouldRun is true.

Example
package main

import (
	"fmt"

	"github.com/SLASH2NL/validate"
)

func main() {
	err := validate.Join(
		validate.Field("email", "test", validate.If(true, validate.Email)),
		validate.Field("iban", "invalid", validate.If(false, validate.IBAN)),
	)
	printError(err)

}

func printError(err error) {
	if err == nil {
		return
	}

	errs := validate.Collect(err)
	for _, e := range errs {
		fmt.Println(e.Error())
	}
}
Output:

validation error for exact path: email, path: email, args: map[], violations: [violation code: email, args: map[]]

func MaxNumber

func MaxNumber[T constraints.Integer | constraints.Float](max T) Validator[T]

func MaxString

func MaxString(length int) Validator[string]

func MinNumber

func MinNumber[T constraints.Integer | constraints.Float](min T) Validator[T]

func MinString

func MinString(length int) Validator[string]

func Not

func Not[T comparable](not T) Validator[T]

Not will validate that the value is not the given value.

func OneOf

func OneOf[T comparable](accepted ...T) Validator[T]

OneOf will validate that the value is one of the accepted values.

func Prefix

func Prefix(prefix string) Validator[string]

func Regex

func Regex(re *regexp.Regexp) Validator[string]

func Resolve

func Resolve[Original any, Resolved any](resolveFunc func(Original) Resolved, validators ...Validator[Resolved]) []Validator[Original]

Resolve will resolve the value and run the validators on the resolved value while preserving the original validator target. This is useful for validating slices or maps where you want to validate a field inside the value.

func Suffix

func Suffix(suffix string) Validator[string]

type Violation

type Violation struct {
	Code string
	Args Args
}

func (Violation) Error

func (v Violation) Error() string

type Violations

type Violations []Violation

func (Violations) Error

func (v Violations) Error() string

Jump to

Keyboard shortcuts

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