validator

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Jan 24, 2025 License: Apache-2.0 Imports: 12 Imported by: 0

README

validator

Description

Validator for structs to validate fields by tag

Validate validates a given struct by vld tags or updates a given struct by upd tags. Validate needs a struct as input and can update the struct by map or json input.

Validate

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 in the struct need a vld tag. If you want to ignore one field in the validator you can add vld:"-". If you don't add the vld tag to every field the function will fail with an error.

Update

You can add a validate tag with the syntax upd:"[json_key], [requirement], [groups]". The json key has to be a valid key from given json for unmarshalling or a key from a given map (eg. gr1min1 gr2max1). Groups are seperated by a space (eg. gr1min1 gr2max1). Conditions and operators in a requirement are seperated by a space (eg. max0 || (min10 && max30)).

Only fields in the struct you want to update need a upd tag.

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

- - ignores the field

equ - equal (value or length)

neq - not equal (value or length)

min - min (value or length)

max - max (value or length)

con - contains

rex - regular expression

Usage of conditions

Conditions have different usages per variable type:

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

rex - regexp.MatchString(condition, strconv.Itoa(int)/strconv.FormatFloat(float, 'f', 3, 64)/string), array ignored

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:"field_name, min1, gr1min1". Usable conditions for groups are min and max.

A small code example would be:

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

ID and CreatedAt are not getting validated, because you would probably not insert these but create these on db 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: benchstat bench.txt.

Creating a new version

To create a new tagged version run eg. git tag v0.1.3. To push and publish it run eg. git push origin v0.1.3.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func UnmapOrUnmarshalRequestValidateAndUpdate added in v0.2.1

func UnmapOrUnmarshalRequestValidateAndUpdate(request *http.Request, structToUpdate interface{}) error

UnmapOrAnmarshalValidateAndUpdate unmarshals given json ([]byte) or given url.Values (from request.Form), validates them and updates the given struct.

func UnmapOrUnmarshalRequestValidateAndUpdateWithValidation added in v0.2.8

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

UnmapOrAnmarshalValidateAndUpdate unmarshals given json ([]byte) or given url.Values (from request.Form), validates them and updates the given map.

func UnmapUrlValuesToJsonMap added in v0.2.1

func UnmapUrlValuesToJsonMap(values url.Values) (model.JsonMap, error)

func UnmapValidateAndUpdate added in v0.2.1

func UnmapValidateAndUpdate(values url.Values, structToUpdate interface{}) error

UnmapValidateAndUpdate unmaps given url.Values into pointer jsonMap. For more information to ValidateAndUpdate look at ValidateAndUpdate(jsonInput model.JsonMap, structToUpdate interface{}) error.

func UnmapValidateAndUpdateWithValidation added in v0.2.8

func UnmapValidateAndUpdateWithValidation(values url.Values, mapToUpdate *model.JsonMap, validations map[string]model.Validation) error

UnmapValidateAndUpdateWithValidation unmaps given url.Values into pointer jsonMap. For more information to ValidateAndUpdate look at ValidateAndUpdate(jsonInput model.JsonMap, structToUpdate interface{}) error.

func UnmarshalAndValidate

func UnmarshalAndValidate(data []byte, v any) error

UnmarshalAndValidate unmarshals given json ([]byte) into pointer v. For more information to Validate look at [Validate(v any) error].

func UnmarshalJsonToJsonMap added in v0.2.1

func UnmarshalJsonToJsonMap(jsonInput []byte) (model.JsonMap, error)

func UnmarshalValidateAndUpdate

func UnmarshalValidateAndUpdate(jsonInput []byte, structToUpdate interface{}) error

UnmarshalValidateAndUpdate unmarshals given json ([]byte) into pointer v. For more information to ValidateAndUpdate look at ValidateAndUpdate(jsonInput model.JsonMap, structToUpdate interface{}) error.

func UnmarshalValidateAndUpdateWithValidation added in v0.2.8

func UnmarshalValidateAndUpdateWithValidation(jsonInput []byte, mapToUpdate *model.JsonMap, validations map[string]model.Validation) error

UnmarshalValidateAndUpdateWithValidation unmarshals given json ([]byte) into pointer mapToUpdate. For more information to ValidateAndUpdate look at ValidateAndUpdate(jsonInput model.JsonMap, structToUpdate interface{}) error.

func Validate

func Validate(v any) error

Validate validates a given struct by vld tags. Validate needs a struct as input.

All fields in the struct need a vld tag. If you want to use multiple conditions you can add them with a space in between them.

A complex example for password would be: `vld:"min8 max30 rex^(.*[A-Z])+(.*)$ rex^(.*[a-z])+(.*)$ rex^(.*\\d)+(.*)$ rex^(.*[\x60!@#$%^&*()_+={};':\"|\\,.<>/?~-])+(.*)$"`

If you want to ignore one field in the validator you can add `vld:"-"`. If you don't add the vld tag to every field the function will fail with an error.

Conditions have different usages per variable type:

equ - int/float/string/bool == condition, len(array) == condition

neq - int/float/string/bool != condition, len(array) != condition

min - int/float >= condition, len(string/array) >= condition

max - int/float <= condition, len(string/array) <= condition

con - strings.Contains(string, condition), contains(array, condition), int/float ignored

rex - regexp.MatchString(condition, int/float/string), array ignored

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.

func ValidateAndUpdate

func ValidateAndUpdate(jsonInput model.JsonMap, structToUpdate interface{}) error

ValidateAndUpdate validates a given struct by upd tags. ValidateAndUpdate needs a struct pointer and a json map as input. The given struct is updated by the values in the json map.

All fields in the struct need a upd tag. The tag has to contain the key value for the json struct. If no tag is present the field in the struct is ignored and does not get updated.

The second part of the tag contains the conditions for the validation.

If you want to use multiple conditions you can add them with a space in between them.

A complex example for password would be: `upd:"password, min8 max30 rex^(.*[A-Z])+(.*)$ rex^(.*[a-z])+(.*)$ rex^(.*\\d)+(.*)$ rex^(.*[\x60!@#$%^&*()_+={};':\"|\\,.<>/?~-])+(.*)$"`

If you want don't want to validate the field you can add `upd:"json_key, -"`. If you don't add the upd tag to every field the function will fail with an error.

Conditions have different usages per variable type:

equ - int/float/string == condition, len(array) == condition

neq - int/float/string != condition, len(array) != condition

min - int/float >= condition, len(string/array) >= condition

max - int/float <= condition, len(string/array) <= condition

con - strings.Contains(string, condition), contains(array, condition), int/float ignored

rex - regexp.MatchString(condition, int/float/string), array ignored

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: `upd:"array, conA"`, good: `upd:"array, 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.

func ValidateAndUpdateWithValidation added in v0.2.8

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

ValidateAndUpdateWithValidation validates a given struct by upd tags. ValidateAndUpdateWithValidation needs a struct pointer, a json map as input and a validation map. The given struct is updated by the values in the json map.

func ValidateValueWithParser added in v0.2.0

func ValidateValueWithParser(input reflect.Value, validation *model.Validation) (interface{}, error)

Types

type StructValue

type StructValue struct {
	Error  error
	Groups []string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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