xvalid

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2023 License: MIT Imports: 6 Imported by: 1

README

xvalid

xvalid is a lightweight validation library that can export rules as JSON so browsers can apply the same rules.

Documentation at godoc.org

Goals

  1. Must be able to export rules so clients can consume them.
  2. Only support common rules such as those found in browsers and GUI libraries e.g. length, min, max etc.
  3. Must be remain legible as number of rules grows and becomes complex.

Comparison

Popuplar validation libraries like go-playground/validate and govalidator are great libraries but they suffer from a few problems.

  1. Since rules are defined in struct tags, errors are less easy to detect, and it becomes too diffult to read when there are many rules and many other struct tags defined. By using methods to define rules, we can rely on compilation checks and can format our code freely.
  2. They compile more regex validators than most project will ever need. By defining only comman validators, we reduce uncessary performance hit; and it is also trivial to copy/paste regex defined by other libraries.
  3. Without being able to export validation rules to client apps, developers will need to be mindful of keeping the rules in sync. By reusing validation rules, you reduce the chance of client and server validating wrongly.

Examples

To define your own validator, you must implement the Validator interface. For example, see any of the validators in validators.go

Define rules and validate objects:

// Store model
type Store struct {
	Name          string     `json:"name"`
	Address       string     `json:"address"`
	Description   string     `json:"description"`
	Tax           int        `json:"tax"`
}

// ValidationRules for this model.
func (store Store) ValidationRules() xvalid.Rules {
	return xvalid.New(&store).
		Field(&store.Name, xvalid.MinStr(4).Optional().SetMessage("Please lengthen name to 4 characters or more"),
			xvalid.MaxStr(80).SetMessage("Please shorten name to 80 characters or less"),
			xvalid.Pattern("^[a-zA-Z0-9_]+$").Optional().SetMessage("Name may contain alphabets, numbers and underscores"),
			xvalid.Pattern("[a-zA-Z]").Optional().SetMessage("Name must contain at least 1 alphabet"),
			xvalid.FieldFunc(func(fieldName string, value interface{}) xvalid.Error {
				name := value.(string)
				if name == "" {
					return nil
				}
				if name == "admin" {
					return xvalid.NewError("This name is not allowed", fieldName)
				}
				return nil
			})).
		Field(&store.Address, xvalid.Required(), xvalid.MaxStr(120)).
		Field(&store.Description, xvalid.MaxStr(1500)).
		Field(&store.Tax, xvalid.MinInt(0), xvalid.MaxInt(100))
}

// Validate the model and return errors if validation fails.
func (store Store) Validate() error {
	return store.ValidationRules().Validate(store)
}

// then validate
store := Store{}
err := store.Validate()
if err != nil {
	panic(err)
}

Export rules as JSON:

func createValidationMap(model ...ruleHolder) map[string]interface{} {
	rules := make(map[string]interface{})
	for _, m := range model {
		rules[reflect.ValueOf(m).Type().Name()] = mapRules(m)
	}
	return rules
}

func mapRules(model ruleHolder) map[string][]interface{} {
	validators := model.ValidationRules().Validators()
	rmap := make(map[string][]interface{})
	for _, v := range validators {
		if !v.HTMLCompatible() {
			continue
		}
		name := v.Name()
		rules, ok := rmap[name]
		if !ok {
			rules = make([]interface{}, 0)
		}
		rules = append(rules, v)
		rmap[name] = rules
	}
	return rmap
}


func main() {
	rules := createValidationMap(model.Member{}, model.Store{}, model.Product{})
	b, err := json.MarshalIndent(rules, "", "	")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}

Documentation

Overview

Package xvalid is a lightweight validation library that can export rules as JSON so browsers can apply the same rules.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsEmail

func IsEmail(email string) bool

IsEmail returns true if the string is an email

Types

type EmailValidator

type EmailValidator struct {
	PatternValidator
}

EmailValidator field must be a valid email address

func Email

func Email() *EmailValidator

Email field must be a valid email address

func (*EmailValidator) MarshalJSON

func (c *EmailValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

type Error

type Error interface {
	Error() string
	Field() string
}

Error when a rule is broken

func NewError

func NewError(message, fieldName string) Error

NewError creates new validation error

type Errors

type Errors []Error

Errors is a list of Error

func (Errors) Error

func (v Errors) Error() string

Error will combine all errors into a list of sentences

type FieldFuncValidator

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

FieldFuncValidator for validating with custom function

func (*FieldFuncValidator) HTMLCompatible

func (c *FieldFuncValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*FieldFuncValidator) Name

func (c *FieldFuncValidator) Name() string

Name of the field

func (*FieldFuncValidator) SetMessage

func (c *FieldFuncValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*FieldFuncValidator) SetName

func (c *FieldFuncValidator) SetName(name string)

SetName of the field

func (*FieldFuncValidator) Validate

func (c *FieldFuncValidator) Validate(value interface{}) Error

Validate the value

type MaxIntValidator

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

MaxIntValidator field have maximum value

func MaxInt

func MaxInt(max int64) *MaxIntValidator

MaxInt field have maximum value

func (*MaxIntValidator) HTMLCompatible

func (c *MaxIntValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*MaxIntValidator) MarshalJSON

func (c *MaxIntValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

func (*MaxIntValidator) Name

func (c *MaxIntValidator) Name() string

Name of the field

func (*MaxIntValidator) SetMessage

func (c *MaxIntValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*MaxIntValidator) SetName

func (c *MaxIntValidator) SetName(name string)

SetName of the field

func (*MaxIntValidator) Validate

func (c *MaxIntValidator) Validate(value interface{}) Error

Validate the value

type MaxStrValidator

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

MaxStrValidator field have maximum length

func MaxStr

func MaxStr(max int64) *MaxStrValidator

MaxStr field have maximum length

func (*MaxStrValidator) HTMLCompatible

func (c *MaxStrValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*MaxStrValidator) MarshalJSON

func (c *MaxStrValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

func (*MaxStrValidator) Name

func (c *MaxStrValidator) Name() string

Name of the field

func (*MaxStrValidator) SetMessage

func (c *MaxStrValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*MaxStrValidator) SetName

func (c *MaxStrValidator) SetName(name string)

SetName of the field

func (*MaxStrValidator) Validate

func (c *MaxStrValidator) Validate(value interface{}) Error

Validate the value

type MinIntValidator

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

MinIntValidator field have minimum value

func MinInt

func MinInt(min int64) *MinIntValidator

MinInt field have minimum value

func (*MinIntValidator) HTMLCompatible

func (c *MinIntValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*MinIntValidator) MarshalJSON

func (c *MinIntValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

func (*MinIntValidator) Name

func (c *MinIntValidator) Name() string

Name of the field

func (*MinIntValidator) Optional

func (c *MinIntValidator) Optional() Validator

Optional don't validate if the value is zero

func (*MinIntValidator) SetMessage

func (c *MinIntValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*MinIntValidator) SetName

func (c *MinIntValidator) SetName(name string)

SetName of the field

func (*MinIntValidator) Validate

func (c *MinIntValidator) Validate(value interface{}) Error

Validate the value

type MinStrValidator

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

MinStrValidator field must have minimum length

func MinStr

func MinStr(min int64) *MinStrValidator

MinStr field must have minimum length

func (*MinStrValidator) HTMLCompatible

func (c *MinStrValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*MinStrValidator) MarshalJSON

func (c *MinStrValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

func (*MinStrValidator) Name

func (c *MinStrValidator) Name() string

Name of the field

func (*MinStrValidator) Optional

func (c *MinStrValidator) Optional() Validator

Optional don't validate if the value is zero

func (*MinStrValidator) SetMessage

func (c *MinStrValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*MinStrValidator) SetName

func (c *MinStrValidator) SetName(name string)

SetName of the field

func (*MinStrValidator) Validate

func (c *MinStrValidator) Validate(value interface{}) Error

Validate the value

type PatternValidator

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

PatternValidator field must match regexp

func Pattern

func Pattern(pattern string) *PatternValidator

Pattern field must match regexp

func (*PatternValidator) HTMLCompatible

func (c *PatternValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*PatternValidator) MarshalJSON

func (c *PatternValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

func (*PatternValidator) Name

func (c *PatternValidator) Name() string

Name of the field

func (*PatternValidator) Optional

func (c *PatternValidator) Optional() Validator

Optional don't validate if the value is zero

func (*PatternValidator) SetMessage

func (c *PatternValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*PatternValidator) SetName

func (c *PatternValidator) SetName(name string)

SetName of the field

func (*PatternValidator) Validate

func (c *PatternValidator) Validate(value interface{}) Error

Validate the value

type RequiredValidator

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

RequiredValidator field must not be zero

func Required

func Required() *RequiredValidator

Required fields must not be zero

func (*RequiredValidator) HTMLCompatible

func (c *RequiredValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*RequiredValidator) MarshalJSON

func (c *RequiredValidator) MarshalJSON() ([]byte, error)

MarshalJSON for this validator

func (*RequiredValidator) Name

func (c *RequiredValidator) Name() string

Name of the field

func (*RequiredValidator) SetMessage

func (c *RequiredValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*RequiredValidator) SetName

func (c *RequiredValidator) SetName(name string)

SetName of the field

func (*RequiredValidator) Validate

func (c *RequiredValidator) Validate(value interface{}) Error

Validate the value

type Rules

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

Rules for creating a chain of rules for validating a struct

func New

func New(structPtr interface{}) Rules

New rule chain

func (Rules) Field

func (r Rules) Field(fieldPtr interface{}, validators ...Validator) Rules

Field adds validators for a field

func (Rules) OnlyFor

func (r Rules) OnlyFor(name string) Rules

OnlyFor filters the validators to match only the fields

func (Rules) Struct

func (r Rules) Struct(validators ...Validator) Rules

Struct adds validators for the struct

func (Rules) Validate

func (r Rules) Validate(subject interface{}) error

Validate a struct and return Errors

func (Rules) Validators

func (r Rules) Validators() []Validator

Validators for this chain

type StructFuncValidator

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

StructFuncValidator validate struct with custom function

func (*StructFuncValidator) HTMLCompatible

func (c *StructFuncValidator) HTMLCompatible() bool

HTMLCompatible for this validator

func (*StructFuncValidator) Name

func (c *StructFuncValidator) Name() string

Name of the field

func (*StructFuncValidator) SetMessage

func (c *StructFuncValidator) SetMessage(msg string) Validator

SetMessage set error message

func (*StructFuncValidator) SetName

func (c *StructFuncValidator) SetName(name string)

SetName of the field

func (*StructFuncValidator) Validate

func (c *StructFuncValidator) Validate(value interface{}) Error

Validate the value

type Validator

type Validator interface {
	SetName(string)
	Name() string
	HTMLCompatible() bool
	SetMessage(string) Validator
	Validate(interface{}) Error
}

Validator to implement a rule

func FieldFunc

func FieldFunc(f func(string, interface{}) Error) Validator

FieldFunc for validating with custom function

func StructFunc

func StructFunc(f func(interface{}) Error) Validator

StructFunc validate struct with custom function

Jump to

Keyboard shortcuts

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