validator

package module
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2025 License: Apache-2.0 Imports: 10 Imported by: 0

README ΒΆ

validator

Go Reference Go Coverage License

Validator for structs and json maps to validate fields by tag.

πŸ’‘ Goal of this package

The goal of the validator package is to provide a fast, simple validation tool that can validate existing structs and validate url values and json bodys to update an empty struct with these values if they are valid.

Main focus is centralisation of validation to one object. You can obviously do one request object for each request type (which is sometimes still needed), but with this package you can do even something like that:

type User struct {
    ID     int    `json:"id" del:"min1"`
    Name   string `json:"name" cre:"min1" upd:"min1, gr1min1"`
    Adress string `json:"adress" cre:"min1" upd:"min1, gr1min1"`
}

You can see the 3 different tags (cre, upd, del). With these tags you can use the same object in 3 different handlers with 3 different validations. In this example for creation you need name and adress, for an update you need at least one of name or adress, and for deletion you need an id greater 0.


πŸ› οΈ Installation

To integrate the validator package into your Go project, use the standard go get command:

go get github.com/siherrmann/validator

πŸš€ Getting started

To begin validating your structs, you either first create a new Validator instance and then invoke its Validate method on your target struct or use the wrapper function.

Here's a simple example demonstrating how to validate a User struct:

type User struct {
    Name  string `vld:"min3"`
    Email string `vld:"rex^[^@]+@[^@]+\\.[^@]+$"`
    Age   int    `vld:"min18"`
}

user := User{
    Name:  "John Doe",
    Email: "john.doe@example.com",
    Age:   25,
}

// Example with validator
v := validator.NewValidator()
err = v.Validate(user)
if err != nil {
    fmt.Println("Validation failed for user:", err)
}

// Example with wrapper functions (uses a new validator instance internally)
err = Validate(user)
if err != nil {
    fmt.Println("Validation failed for user:", err)
}

In these examples:

  • vld:"min3": Ensures the string field Name has a minimum length of 3 characters.
  • vld:"rex^[^@]+@[^@]+\\.[^@]+$": Validates Email against a regular expression pattern.
  • vld:"min18": Checks that the integer field Age has a minimum value of 18.

If you want to directly validate bytes and update for example the User struct if the values are valid you can use UnmapOrUnmarshalValidateAndUpdate.

func CreateUser(w http.ResponseWriter, r *http.Request) {
    user := &User{}
    err := v.UnmapOrUnmarshalValidateAndUpdate(r, user)
    if err != nil {
        fmt.Println("Validation failed for new user:", err)
    }
    ...
}

If you want to use the User struct for multiple handlers like CreateUser, UpdateUser and DeleteUser, you could use custom tags like this:

type User struct {
    ID    int    `delete:"min1"`
    Name  string `create:"min3" update:"min3, gr1min1"`
    Email string `create:"rex^[^@]+@[^@]+\\.[^@]+$" update:"rex^[^@]+@[^@]+\\.[^@]+$, gr1min1"`
    Age   int    `create:"min18" update:"min18, gr1min1"`
}

func CreateUser(w http.ResponseWriter, r *http.Request) {
    user := &User{}
    err := v.UnmapOrUnmarshalValidateAndUpdate(r, user, "create")
    if err != nil {
        fmt.Println("Validation failed for new user:", err)
    }
    ...
}

func UpdateUser(w http.ResponseWriter, r *http.Request) {
    user := &User{}
    err := v.UnmapOrUnmarshalValidateAndUpdate(r, user, "update")
    if err != nil {
        fmt.Println("Validation failed for new user:", err)
    }
    ...
}

func DeleteUser(w http.ResponseWriter, r *http.Request) {
    user := &User{}
    err := v.UnmapOrUnmarshalValidateAndUpdate(r, user, "delete")
    if err != nil {
        fmt.Println("Validation failed for new user:", err)
    }
    ...
}

Validation

Validate validates a given struct by vld or custom tags. ValidateAndUpdate does update the given struct with the given json after validating the json. UnmarshalValidateAndUpdate and similar functions are unpacking something (request body or url values), then validating the input and updating the given struct. ValidateAndUpdateWithValidation gives you the ability to update a map with the values from a json map by using an array of Validation (which is the equivalent for tags in a struct).

You can add a validate tag with the syntax vld:"[requirement], [groups]". Groups are seperated by a space (eg. gr1min1 gr2max1). Conditions and operators in a requirement are seperated by a space (eg. max0 || (min10 && max30)).

All fields that you want to validate in the struct need a vld tag (or custom tag if specified). If you don't want to validate the field you can add vld:"-". If you then use an update function it does update it without validating.

Requirement

You can build complex requirements by building a query of conditions, operators (&& (=AND) and || (=OR)) and groups (with ( and )).

A complex example for a password check (min length 8, max length 30, at least one capital letter, one small letter, one digit and one special character) would be: vld:"min8 max30 rex^(.*[A-Z])+(.*)$ rex^(.*[a-z])+(.*)$ rex^(.*\\d)+(.*)$ rex^(.*[\x60!@#$%^&*()_+={};':\"|\\,.<>/?~-])+(.*)$". In this example all connections are && (=AND) connections. Because behind the requirement check is a little parser you can also do more complex requirements with multiple conditions grouped and connected with AND and OR connections. You can do for example vld:"max0 || ((min10 && max30) || equTest)" for a string that has to be either empty, the string Test or between 10 and 30 characters long. And yes, the outer brackets are not needed πŸ˜‰.

Condition types

Conditions have different usages per variable type:

  • - - Not validating/update without validating.
  • equ - int/float/string == condition, len(array) == condition
  • neq - int/float/string != condition, len(array) != condition
  • min - int/float >= condition, len(strings.TrimSpace(string)/array) >= condition
  • max - int/float <= condition, len(strings.TrimSpace(string)/array) <= condition
  • con - strings.Contains(string, condition), contains(array, condition), int/float ignored
  • nco - !strings.Contains(string, condition), !contains(array, condition), int/float ignored
  • frm - Checks if given comma seperated list contains value/every item in array/every key in map.
  • nfr - Checks if given comma seperated list does not contain value/every item in array/every key in map.
  • rex - regexp.MatchString(condition, strconv.Itoa(int)/strconv.FormatFloat(float, 'f', 3, 64)/string), array ignored
  • fun - Checks the value with a custom function. The function has to be added to the validator, so it does not work with the wrapped functions. It can be used beside other requirements like min3 && funYourCheckFunction. This also allows you to check unsupported types by only using funYourCheckFunction.

For con you need to put in a condition that is convertable to the underlying type of the arrary. Eg. for an array of int the condition must be convertable to int (bad: vld:"conA", good: vld:"con1").

In the case of rex the int and float input will get converted to a string (strconv.Itoa(int) and fmt.Sprintf("%f", f)). If you want to check more complex cases you can obviously replace equ, neq, min, max and con with one regular expression.

Groups

You also have the posibillity to add groups. So if you want to check on an update, that at least one field is updated, you can add all fields to a group upd:"min1, gr1min1". Usable conditions for groups are min and max.

A small code example would be:

type Error struct {
    ID                  int       `json:"id"`
    StatusCode          int       `json:"status_code" vld:"min100" upd:"min100, gr1min1"`
    Message             string    `json:"message" vld:"min1" upd:"min1, gr1min1"`
    UnderlyingException string    `json:"underlying_exception" vld:"min1, gr1min1" upd:"min1, gr1min1"`
    CreatedAt           time.Time `json:"created_at" vld:"-"`
}

ID and CreatedAt in this example are not getting validated, because you would probably not insert these but create these on database level. StatusCode is necessary on creation and on update it is in a group with Message and UnderlyingException where one of them must be given. One of Message and UnderlyingException is required on creation.


Testing

To run the tests run go test ./....

Benchmark

To run benchmarks run go test -bench . -count 100 > bench.txt (with memory allocation would be go test -bench . -benchmem -count 100 > bench.txt but they are 0). To see the results in a nice way after the run install go install golang.org/x/perf/cmd/benchstat@latest and log the results to the console with benchstat bench.txt.


⭐ Features

  • Validate json or form values by struct tag.
  • Validate json or form values by validations.
  • Validate and update a struct from JsonMap.
  • Tag-based validation: Define validation rules directly within struct tags using a concise syntax (e.g. vld:"(min3 && ncotest) || max0"). Use multiple custom tags in one struct for multiple validation situations. The dafault tag is vld.
  • Custom validation functions: Extend the validation capabilities by registering and using your own custom validation logic. Use it beside other requirements like min3 && funYourCheckFunction. This also allows you to check unsupported types by only using funYourCheckFunction.
  • Nested struct support: Seamlessly validate complex data structures containing nested structs.
  • Array validation: Apply validation rules to elements within arrays and slices.
  • Grouped validations: Organize validation rules into logical groups for more granular control.
  • Advanced logical conditions: Implement complex validation scenarios using logical operators (e.g., AND, OR) within your tags.

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func UnmapAndValidate ΒΆ added in v0.5.0

func UnmapAndValidate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapAndValidate is the wrapper function for the UnmapAndValidate method of the Validator struct. More details can be found in the UnmapAndValidate method.

func UnmapOrUnmarshalAndValidate ΒΆ added in v0.5.0

func UnmapOrUnmarshalAndValidate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapOrUnmarshalAndValidate is the wrapper function for the UnmapOrUnmarshalAndValidate method of the Validator struct. More details can be found in the UnmapOrUnmarshalAndValidate method.

func UnmapOrUnmarshalValidateAndUpdate ΒΆ added in v0.5.0

func UnmapOrUnmarshalValidateAndUpdate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapOrUnmarshalValidateAndUpdate is the wrapper function for the UnmapOrUnmarshalValidateAndUpdate method of the Validator struct. More details can be found in the UnmapOrUnmarshalValidateAndUpdate method.

func UnmapOrUnmarshalValidateAndUpdateWithValidation ΒΆ added in v0.5.0

func UnmapOrUnmarshalValidateAndUpdateWithValidation(request *http.Request, mapToUpdate *map[string]any, validations []model.Validation) error

UnmapOrUnmarshalValidateAndUpdateWithValidation is the wrapper function for the UnmapOrUnmarshalValidateAndUpdateWithValidation method of the Validator struct. More details can be found in the UnmapOrUnmarshalValidateAndUpdateWithValidation method.

func UnmapValidateAndUpdate ΒΆ added in v0.2.1

func UnmapValidateAndUpdate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapValidateAndUpdate is the wrapper function for the UnmapValidateAndUpdate method of the Validator struct. More details can be found in the UnmapValidateAndUpdate method.

func UnmapValidateAndUpdateWithValidation ΒΆ added in v0.2.8

func UnmapValidateAndUpdateWithValidation(request *http.Request, mapToUpdate *map[string]any, validations []model.Validation) error

UnmapValidateAndUpdateWithValidation is the wrapper function for the UnmapValidateAndUpdateWithValidation method of the Validator struct. More details can be found in the UnmapValidateAndUpdateWithValidation method.

func UnmarshalAndValidate ΒΆ

func UnmarshalAndValidate(request *http.Request, v any, tagType ...string) error

UnmarshalAndValidate is the wrapper function for the UnmarshalAndValidate method of the Validator struct. More details can be found in the UnmarshalAndValidate method.

func UnmarshalValidateAndUpdate ΒΆ

func UnmarshalValidateAndUpdate(request *http.Request, structToUpdate any, tagType ...string) error

UnmarshalValidateAndUpdate is the wrapper function for the UnmarshalValidateAndUpdate method of the Validator struct. More details can be found in the UnmarshalValidateAndUpdate method.

func UnmarshalValidateAndUpdateWithValidation ΒΆ added in v0.2.8

func UnmarshalValidateAndUpdateWithValidation(request *http.Request, mapToUpdate *map[string]any, validations []model.Validation) error

UnmarshalValidateAndUpdateWithValidation is the wrapper function for the UnmarshalValidateAndUpdateWithValidation method of the Validator struct. More details can be found in the UnmarshalValidateAndUpdateWithValidation method.

func Validate ΒΆ

func Validate(v any, tagType ...string) error

Validate is the wrapper function for the Validate method of the Validator struct. More details can be found in the Validate method.

func ValidateAndUpdate ΒΆ

func ValidateAndUpdate(jsonInput map[string]any, structToUpdate any, tagType ...string) error

ValidateAndUpdate is the wrapper function for the ValidateAndUpdate method of the Validator struct. More details can be found in the ValidateAndUpdate method.

func ValidateAndUpdateWithValidation ΒΆ added in v0.2.8

func ValidateAndUpdateWithValidation(jsonInput map[string]any, mapToUpdate *map[string]any, validations []model.Validation) error

ValidateAndUpdateWithValidation is the wrapper function for the ValidateAndUpdateWithValidation method of the Validator struct. More details can be found in the ValidateAndUpdateWithValidation method.

func ValidateWithValidation ΒΆ added in v0.4.0

func ValidateWithValidation(jsonInput map[string]any, validations []model.Validation) (map[string]any, error)

ValidateWithValidation is the wrapper function for the ValidateWithValidation method of the Validator struct. More details can be found in the ValidateWithValidation method.

Types ΒΆ

type ValidationFunc ΒΆ added in v0.5.0

type ValidationFunc func(input any, astValue *model.AstValue) error

type Validator ΒΆ added in v0.5.0

type Validator struct {
	ValidationFuncs map[string]ValidationFunc
}

Validator is the main struct for validation.

func NewValidator ΒΆ added in v0.5.0

func NewValidator() *Validator

NewValidator creates a new Validator instance with an empty validation functions map.

func (*Validator) AddValidationFunc ΒΆ added in v0.5.0

func (r *Validator) AddValidationFunc(fn ValidationFunc, name string)

AddValidationFunc adds a custom validation function to the Validator. The function can be used in validation requirements with the name provided (`fun<name>`).

func (*Validator) RunValidatorsOnConditionGroup ΒΆ added in v0.5.0

func (r *Validator) RunValidatorsOnConditionGroup(input any, astValue *model.AstValue) error

RunFuncOnConditionGroup runs the function [f] on each condition in the [astValue]. If the condition is a group, it recursively calls itself on the group. If the condition is a condition, it calls the function [f] with the input and the condition. If the operator is AND, it returns an error if any condition fails. If the operator is OR, it collects all errors and returns them if all conditions fail.

func (*Validator) UnmapAndValidate ΒΆ added in v0.5.0

func (r *Validator) UnmapAndValidate(request *http.Request, structToValidate any, tagType ...string) error

UnmapAndValidate unmaps the url.Values from the request.Form into a JsonMap and puts it into the given struct. It validates the struct by the given tagType. It returns an error if the unmapping or validation fails.

It is actually doing the same as UnmapValidateAndUpdate, but in another order. It does directly update the struct and validates afterwards. Normally you would either only use Validate or use UnmapValidateAndUpdate for early return on error.

func (*Validator) UnmapOrUnmarshalAndValidate ΒΆ added in v0.5.0

func (r *Validator) UnmapOrUnmarshalAndValidate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapOrUnmarshalAndValidate unmarshals given json ([]byte) or given url.Values (from request.Form), validates them and updates the given struct. It returns an error if the unmapping or validation fails.

It is actually doing the same as UnmapOrUnmarshalValidateAndUpdate, but in another order. It does directly update the struct and validates afterwards. Normally you would either only use Validate or use UnmapOrUnmarshalValidateAndUpdate for early return on error.

func (*Validator) UnmapOrUnmarshalValidateAndUpdate ΒΆ added in v0.5.0

func (r *Validator) UnmapOrUnmarshalValidateAndUpdate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapOrUnmarshalValidateAndUpdate unmarshals given json ([]byte) or given url.Values (from request.Form), validates them and updates the given struct. It returns an error if the unmapping, validation or update fails.

For more information look at ValidateAndUpdate.

func (*Validator) UnmapOrUnmarshalValidateAndUpdateWithValidation ΒΆ added in v0.5.0

func (r *Validator) UnmapOrUnmarshalValidateAndUpdateWithValidation(request *http.Request, mapToUpdate *map[string]any, validations []model.Validation) error

UnmapOrUnmarshalValidateAndUpdateWithValidation unmarshals given json ([]byte) or given url.Values (from request.Form). It validates the map with the given validations and updates the given map. It returns an error if the unmapping, validation or update fails.

func (*Validator) UnmapValidateAndUpdate ΒΆ added in v0.5.0

func (r *Validator) UnmapValidateAndUpdate(request *http.Request, structToUpdate any, tagType ...string) error

UnmapValidateAndUpdate unmaps given url.Values into pointer jsonMap. It returns an error if the unmapping, validation or update fails.

For more information look at ValidateAndUpdate.

func (*Validator) UnmapValidateAndUpdateWithValidation ΒΆ added in v0.5.0

func (r *Validator) UnmapValidateAndUpdateWithValidation(request *http.Request, mapToUpdate *map[string]any, validations []model.Validation) error

UnmapValidateAndUpdateWithValidation unmaps given url.Values into pointer jsonMap. It validates the map by the given validations and updates it. It returns an error if the unmapping, validation or update fails.

func (*Validator) UnmarshalAndValidate ΒΆ added in v0.5.0

func (r *Validator) UnmarshalAndValidate(request *http.Request, structToValidate any, tagType ...string) error

UnmarshalAndValidate unmarshals given json ([]byte) into pointer v. It validates the struct by the given tagType. It returns an error if the unmarshaling or validation fails.

It is actually doing the same as UnmarshalValidateAndUpdate, but in another order. It does directly update the struct and validates afterwards. Normally you would either only use Validate or use UnmarshalValidateAndUpdate for early return on error.

func (*Validator) UnmarshalValidateAndUpdate ΒΆ added in v0.5.0

func (r *Validator) UnmarshalValidateAndUpdate(request *http.Request, structToUpdate any, tagType ...string) error

UnmarshalValidateAndUpdate unmarshals given json ([]byte) into pointer v. It returns an error if the unmapping, validation or update fails.

For more information look at ValidateAndUpdate.

func (*Validator) UnmarshalValidateAndUpdateWithValidation ΒΆ added in v0.5.0

func (r *Validator) UnmarshalValidateAndUpdateWithValidation(request *http.Request, mapToUpdate *map[string]any, validations []model.Validation) error

UnmarshalValidateAndUpdateWithValidation unmarshals given json ([]byte) into pointer mapToUpdate. It validates the map by the given validations and updates it. It returns an error if the unmarshaling, validation or update fails.

func (*Validator) Validate ΒΆ added in v0.5.0

func (r *Validator) Validate(v any, tagType ...string) error

Validate validates a given struct by the given tagType. It checks if the keys are in the struct and validates the values. It returns an error if the validation fails.

func (*Validator) ValidateAndUpdate ΒΆ added in v0.5.0

func (r *Validator) ValidateAndUpdate(jsonInput map[string]any, structToUpdate any, tagType ...string) error

ValidateAndUpdate validates a given JsonMap by the given validations and updates the struct. It checks if the keys are in the map, validates the values and updates the struct if the validation passes. It returns an error if the validation fails or if the struct cannot be updated.

func (*Validator) ValidateAndUpdateWithValidation ΒΆ added in v0.5.0

func (r *Validator) ValidateAndUpdateWithValidation(jsonInput map[string]any, mapToUpdate *map[string]any, validations []model.Validation) error

ValidateAndUpdateWithValidation validates a given JsonMap by the given validations and updates the map. It checks if the keys are in the map, validates the values and updates the map if the validation passes. It returns an error if the validation fails or if the map cannot be updated.

func (*Validator) ValidateValueWithParser ΒΆ added in v0.5.0

func (r *Validator) ValidateValueWithParser(input any, validation *model.Validation) error

ValidateValueWithParser validates a value against a given validation using the parser. It parses the validation requirement and runs the validation function on the input value.

It returns an error if the validation fails.

func (*Validator) ValidateWithValidation ΒΆ added in v0.5.0

func (r *Validator) ValidateWithValidation(jsonInput map[string]any, validations []model.Validation) (map[string]any, error)

ValidateWithValidation validates a given JsonMap by the given validations. This is the main validation function that is used for all validation. It checks if the keys are in the map, validates the values and returns a new JsonMap.

If a validation has groups, it checks if the values are valid for the groups. If a validation has a key that is already in the map, it returns an error.

It returns a new JsonMap with the validated values or an error if the validation fails.

Directories ΒΆ

Path Synopsis

Jump to

Keyboard shortcuts

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