Documentation
¶
Overview ¶
Package validation provides tools for data validation. It is designed to create complex validation rules with abilities to hook into the validation process.
Index ¶
- Constants
- func Filter(violations ...error) error
- func IsViolation(err error) bool
- func IsViolationList(err error) bool
- type Argument
- type ArrayIndexElement
- type AtLeastOneOfArgument
- type BoolConstraint
- type Checker
- type ComparableConstraint
- type ComparablesConstraint
- type ConstraintAlreadyStoredError
- type ConstraintError
- type ConstraintNotFoundError
- type CountableConstraint
- type CustomStringConstraint
- func (c CustomStringConstraint) Code(code string) CustomStringConstraint
- func (c CustomStringConstraint) Message(template string, parameters ...TemplateParameter) CustomStringConstraint
- func (c CustomStringConstraint) ValidateString(value *string, scope Scope) error
- func (c CustomStringConstraint) When(condition bool) CustomStringConstraint
- func (c CustomStringConstraint) WhenGroups(groups ...string) CustomStringConstraint
- type NewViolationFunc
- type NilConstraint
- type NumberConstraint
- type Numeric
- type Option
- type PropertyNameElement
- type PropertyPath
- type PropertyPathElement
- type Scope
- func (s Scope) AtIndex(index int) Scope
- func (s Scope) AtProperty(name string) Scope
- func (s Scope) BuildViolation(code, message string) *ViolationBuilder
- func (s Scope) Context() context.Context
- func (s Scope) IsApplied(groups ...string) bool
- func (s Scope) IsIgnored(groups ...string) bool
- func (s Scope) NewConstraintError(constraintName, description string) ConstraintError
- func (s Scope) Validator() *Validator
- type SequentialArgument
- type StringConstraint
- type TemplateParameter
- type TemplateParameterList
- type TimeConstraint
- type Translator
- type Validatable
- type ValidateOnScopeFunc
- type Validator
- func (validator *Validator) AtIndex(index int) *Validator
- func (validator *Validator) AtProperty(name string) *Validator
- func (validator *Validator) BuildViolation(ctx context.Context, code, message string) *ViolationBuilder
- func (validator *Validator) GetConstraint(key string) interface{}
- func (validator *Validator) Validate(ctx context.Context, arguments ...Argument) error
- func (validator *Validator) ValidateBool(ctx context.Context, value bool, constraints ...BoolConstraint) error
- func (validator *Validator) ValidateCountable(ctx context.Context, count int, constraints ...CountableConstraint) error
- func (validator *Validator) ValidateEachString(ctx context.Context, values []string, constraints ...StringConstraint) error
- func (validator *Validator) ValidateFloat(ctx context.Context, value float64, constraints ...NumberConstraint[float64]) error
- func (validator *Validator) ValidateInt(ctx context.Context, value int, constraints ...NumberConstraint[int]) error
- func (validator *Validator) ValidateIt(ctx context.Context, validatable Validatable) error
- func (validator *Validator) ValidateString(ctx context.Context, value string, constraints ...StringConstraint) error
- func (validator *Validator) ValidateStrings(ctx context.Context, values []string, ...) error
- func (validator *Validator) ValidateTime(ctx context.Context, value time.Time, constraints ...TimeConstraint) error
- func (validator *Validator) WithGroups(groups ...string) *Validator
- func (validator *Validator) WithLanguage(tag language.Tag) *Validator
- type ValidatorArgument
- func Bool(value bool, constraints ...BoolConstraint) ValidatorArgument
- func BoolProperty(name string, value bool, constraints ...BoolConstraint) ValidatorArgument
- func CheckNoViolations(err error) ValidatorArgument
- func Comparable[T comparable](value T, constraints ...ComparableConstraint[T]) ValidatorArgument
- func ComparableProperty[T comparable](name string, value T, constraints ...ComparableConstraint[T]) ValidatorArgument
- func Comparables[T comparable](values []T, constraints ...ComparablesConstraint[T]) ValidatorArgument
- func ComparablesProperty[T comparable](name string, values []T, constraints ...ComparablesConstraint[T]) ValidatorArgument
- func Countable(count int, constraints ...CountableConstraint) ValidatorArgument
- func CountableProperty(name string, count int, constraints ...CountableConstraint) ValidatorArgument
- func EachComparable[T comparable](values []T, constraints ...ComparableConstraint[T]) ValidatorArgument
- func EachComparableProperty[T comparable](name string, values []T, constraints ...ComparableConstraint[T]) ValidatorArgument
- func EachNumber[T Numeric](values []T, constraints ...NumberConstraint[T]) ValidatorArgument
- func EachNumberProperty[T Numeric](name string, values []T, constraints ...NumberConstraint[T]) ValidatorArgument
- func EachString(values []string, constraints ...StringConstraint) ValidatorArgument
- func EachStringProperty(name string, values []string, constraints ...StringConstraint) ValidatorArgument
- func NewArgument(validate ValidateOnScopeFunc) ValidatorArgument
- func Nil(isNil bool, constraints ...NilConstraint) ValidatorArgument
- func NilBool(value *bool, constraints ...BoolConstraint) ValidatorArgument
- func NilBoolProperty(name string, value *bool, constraints ...BoolConstraint) ValidatorArgument
- func NilComparable[T comparable](value *T, constraints ...ComparableConstraint[T]) ValidatorArgument
- func NilComparableProperty[T comparable](name string, value *T, constraints ...ComparableConstraint[T]) ValidatorArgument
- func NilNumber[T Numeric](value *T, constraints ...NumberConstraint[T]) ValidatorArgument
- func NilNumberProperty[T Numeric](name string, value *T, constraints ...NumberConstraint[T]) ValidatorArgument
- func NilProperty(name string, isNil bool, constraints ...NilConstraint) ValidatorArgument
- func NilString(value *string, constraints ...StringConstraint) ValidatorArgument
- func NilStringProperty(name string, value *string, constraints ...StringConstraint) ValidatorArgument
- func NilTime(value *time.Time, constraints ...TimeConstraint) ValidatorArgument
- func NilTimeProperty(name string, value *time.Time, constraints ...TimeConstraint) ValidatorArgument
- func Number[T Numeric](value T, constraints ...NumberConstraint[T]) ValidatorArgument
- func NumberProperty[T Numeric](name string, value T, constraints ...NumberConstraint[T]) ValidatorArgument
- func String(value string, constraints ...StringConstraint) ValidatorArgument
- func StringProperty(name string, value string, constraints ...StringConstraint) ValidatorArgument
- func Time(value time.Time, constraints ...TimeConstraint) ValidatorArgument
- func TimeProperty(name string, value time.Time, constraints ...TimeConstraint) ValidatorArgument
- func Valid(value Validatable) ValidatorArgument
- func ValidMap[T Validatable](values map[string]T) ValidatorArgument
- func ValidMapProperty[T Validatable](name string, values map[string]T) ValidatorArgument
- func ValidProperty(name string, value Validatable) ValidatorArgument
- func ValidSlice[T Validatable](values []T) ValidatorArgument
- func ValidSliceProperty[T Validatable](name string, values []T) ValidatorArgument
- type ValidatorOption
- func DefaultLanguage(tag language.Tag) ValidatorOption
- func SetTranslator(translator Translator) ValidatorOption
- func SetViolationFactory(factory ViolationFactory) ValidatorOption
- func StoredConstraint(key string, constraint interface{}) ValidatorOption
- func Translations(messages map[language.Tag]map[string]catalog.Message) ValidatorOption
- type ValidatorOptions
- type Violation
- type ViolationBuilder
- func (b *ViolationBuilder) AddParameter(name, value string) *ViolationBuilder
- func (b *ViolationBuilder) BuildViolation(code, message string) *ViolationBuilder
- func (b *ViolationBuilder) CreateViolation() Violation
- func (b *ViolationBuilder) SetLanguage(tag language.Tag) *ViolationBuilder
- func (b *ViolationBuilder) SetParameters(parameters ...TemplateParameter) *ViolationBuilder
- func (b *ViolationBuilder) SetPluralCount(pluralCount int) *ViolationBuilder
- func (b *ViolationBuilder) SetPropertyPath(path *PropertyPath) *ViolationBuilder
- type ViolationFactory
- type ViolationList
- func (list *ViolationList) Append(violations ...Violation)
- func (list *ViolationList) AppendFromError(err error) error
- func (list *ViolationList) AsError() error
- func (list *ViolationList) AsSlice() []Violation
- func (list *ViolationList) Each(f func(i int, violation Violation) error) error
- func (list *ViolationList) Error() string
- func (list *ViolationList) Filter(codes ...string) *ViolationList
- func (list *ViolationList) First() *ViolationListElement
- func (list *ViolationList) Has(codes ...string) bool
- func (list *ViolationList) Join(violations *ViolationList)
- func (list *ViolationList) Last() *ViolationListElement
- func (list *ViolationList) Len() int
- func (list *ViolationList) MarshalJSON() ([]byte, error)
- type ViolationListElement
- func (element *ViolationListElement) Code() string
- func (element *ViolationListElement) Error() string
- func (element *ViolationListElement) Is(codes ...string) bool
- func (element *ViolationListElement) Message() string
- func (element *ViolationListElement) MessageTemplate() string
- func (element *ViolationListElement) Next() *ViolationListElement
- func (element *ViolationListElement) Parameters() []TemplateParameter
- func (element *ViolationListElement) PropertyPath() *PropertyPath
- func (element *ViolationListElement) Violation() Violation
- type WhenArgument
- type WhenGroupsArgument
Examples ¶
- AtLeastOneOf
- Bool
- BoolProperty
- Check
- CheckNoViolations
- CheckProperty
- Comparable (Int)
- Comparable (String)
- ComparableProperty (Int)
- ComparableProperty (String)
- Comparables
- ComparablesProperty
- Countable
- CountableProperty
- EachComparable
- EachComparableProperty
- EachNumber
- EachNumberProperty
- EachString
- EachStringProperty
- Language
- NewArgument (CustomArgumentConstraintValidator)
- NewCustomStringConstraint
- NewValidator
- Nil
- NilBool
- NilBoolProperty
- NilComparable (Int)
- NilComparable (String)
- NilComparableProperty (Int)
- NilComparableProperty (String)
- NilNumber (Float)
- NilNumber (Int)
- NilNumberProperty (Float)
- NilNumberProperty (Int)
- NilProperty
- NilString
- NilStringProperty
- NilTime
- NilTimeProperty
- Number (Float)
- Number (Int)
- NumberProperty (Float)
- NumberProperty (Int)
- Scope.Validator
- Sequentially
- StoredConstraint
- String
- StringProperty
- Time
- TimeProperty
- Translations
- Valid (ValidatableSlice)
- Valid (ValidatableStruct)
- Validator.AtIndex
- Validator.AtProperty
- Validator.BuildViolation (BuildingViolation)
- Validator.BuildViolation (TranslatableParameter)
- Validator.GetConstraint (CustomServiceConstraint)
- Validator.Validate (BasicStructValidation)
- Validator.Validate (BasicValidation)
- Validator.Validate (ConditionalValidationOnConstraint)
- Validator.Validate (CustomConstraint)
- Validator.Validate (CustomizingErrorMessage)
- Validator.Validate (HttpHandler)
- Validator.Validate (PassingPropertyPathViaOptions)
- Validator.Validate (PropertyPathBySpecialArgument)
- Validator.Validate (PropertyPathWithScopedValidator)
- Validator.Validate (SingletonValidator)
- Validator.Validate (TranslationForCustomMessage)
- Validator.Validate (TranslationsByArgument)
- Validator.Validate (TranslationsByContextArgument)
- Validator.Validate (TranslationsByDefaultLanguage)
- Validator.Validate (UsingContextWithRecursion)
- Validator.ValidateBool
- Validator.ValidateCountable
- Validator.ValidateEachString
- Validator.ValidateFloat
- Validator.ValidateInt
- Validator.ValidateIt
- Validator.ValidateString
- Validator.ValidateStrings
- Validator.ValidateTime
- Validator.WithGroups
- Validator.WithLanguage
- ViolationList.AppendFromError (AddingError)
- ViolationList.AppendFromError (AddingViolation)
- ViolationList.AppendFromError (AddingViolationList)
- ViolationList.First
- When
- WhenArgument.Else
- WhenArgument.Then
Constants ¶
const DefaultGroup = "default"
Variables ¶
This section is empty.
Functions ¶
func Filter ¶
Filter is used for processing the list of errors to return a single ViolationList. If there is at least one non-violation error it will return it instead.
func IsViolation ¶
IsViolation can be used to verify that the error implements the Violation interface.
func IsViolationList ¶
IsViolationList can be used to verify that the error implements the ViolationList.
Types ¶
type Argument ¶
type Argument interface {
// contains filtered or unexported methods
}
Argument used to set up the validation process. It is used to set up the current validation scope and to pass arguments for validation values.
func Language ¶
Language argument sets the current language for translation of a violation message.
Example ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator(validation.Translations(russian.Messages)) if err != nil { log.Fatal(err) } s := "" err = validator.Validate( context.Background(), validation.Language(language.Russian), validation.String(s, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: Значение не должно быть пустым.
type ArrayIndexElement ¶
type ArrayIndexElement int
ArrayIndexElement holds up array index value under PropertyPath.
func (ArrayIndexElement) IsIndex ¶
func (a ArrayIndexElement) IsIndex() bool
IsIndex on ArrayIndexElement always returns true.
func (ArrayIndexElement) String ¶
func (a ArrayIndexElement) String() string
String returns array index values converted into a string.
type AtLeastOneOfArgument ¶ added in v0.9.0
type AtLeastOneOfArgument struct {
// contains filtered or unexported fields
}
AtLeastOneOfArgument can be used to set up validation process to check that the value satisfies at least one of the given constraints. The validation stops as soon as one constraint is satisfied.
func AtLeastOneOf ¶ added in v0.3.0
func AtLeastOneOf(arguments ...Argument) AtLeastOneOfArgument
AtLeastOneOf can be used to set up validation process to check that the value satisfies at least one of the given constraints. The validation stops as soon as one constraint is satisfied.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { banners := []struct { Name string Keywords []string Companies []string Brands []string }{ {Name: "Acme banner", Companies: []string{"Acme"}}, {Name: "Empty banner"}, } for _, banner := range banners { err := validator.Validate( context.Background(), validation.AtLeastOneOf( validation.CountableProperty("keywords", len(banner.Keywords), it.IsNotBlank()), validation.CountableProperty("companies", len(banner.Companies), it.IsNotBlank()), validation.CountableProperty("brands", len(banner.Brands), it.IsNotBlank()), ), ) if violations, ok := validation.UnwrapViolationList(err); ok { fmt.Println("banner", banner.Name, "is not valid:") for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } } }
Output: banner Empty banner is not valid: violation at 'keywords': This value should not be blank. violation at 'companies': This value should not be blank. violation at 'brands': This value should not be blank.
func (AtLeastOneOfArgument) When ¶ added in v0.9.0
func (arg AtLeastOneOfArgument) When(condition bool) AtLeastOneOfArgument
When enables conditional validation of this argument. If the expression evaluates to false, then the argument will be ignored.
func (AtLeastOneOfArgument) With ¶ added in v0.9.0
func (arg AtLeastOneOfArgument) With(options ...Option) AtLeastOneOfArgument
With returns a copy of AtLeastOneOfArgument with appended options.
type BoolConstraint ¶
BoolConstraint is used to build constraints for boolean values validation.
type Checker ¶ added in v0.5.2
type Checker struct {
// contains filtered or unexported fields
}
Checker is an argument that can be useful for quickly checking the result of some simple expression that returns a boolean value.
func Check ¶ added in v0.5.2
Check argument can be useful for quickly checking the result of some simple expression that returns a boolean value.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) func main() { v := 123 err := validator.Validate(context.Background(), validation.Check(v > 321)) fmt.Println(err) }
Output: violation: This value is not valid.
func CheckProperty ¶ added in v0.5.2
CheckProperty argument is an alias for Check that automatically adds property name to the current scope. It is useful to apply a simple checks on structs.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) type Outlet struct { Type string MainCommodity OutletCommodity } type OutletCommodity interface { Name() string Supports(outletType string) bool } type DigitalMovie struct { name string } func (m DigitalMovie) Name() string { return m.name } func (m DigitalMovie) Supports(outletType string) bool { return outletType == "digital" } func main() { outlet := Outlet{ Type: "offline", MainCommodity: DigitalMovie{name: "Digital movie"}, } err := validator.Validate( context.Background(), validation. CheckProperty("mainCommodity", outlet.MainCommodity.Supports(outlet.Type)). Code("unsupportedCommodity"). Message( `Commodity "{{ value }}" cannot be sold at outlet.`, validation.TemplateParameter{Key: "{{ value }}", Value: outlet.MainCommodity.Name()}, ), ) if violations, ok := validation.UnwrapViolationList(err); ok { for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println("violation code:", violation.Code()) fmt.Println(violation) } } }
Output: violation code: unsupportedCommodity violation at 'mainCommodity': Commodity "Digital movie" cannot be sold at outlet.
func (Checker) Message ¶ added in v0.5.2
func (c Checker) Message(template string, parameters ...TemplateParameter) Checker
Message sets the violation message template. You can set custom template parameters for injecting its values into the final message.
func (Checker) When ¶ added in v0.5.3
When enables conditional validation of this constraint. If the expression evaluates to false, then the constraint will be ignored.
func (Checker) WhenGroups ¶ added in v0.8.0
WhenGroups enables conditional validation of the constraint by using the validation groups.
type ComparableConstraint ¶ added in v0.9.0
type ComparableConstraint[T comparable] interface { ValidateComparable(value *T, scope Scope) error }
ComparableConstraint is used to build constraints for generic comparable value validation.
type ComparablesConstraint ¶ added in v0.9.0
type ComparablesConstraint[T comparable] interface { ValidateComparables(values []T, scope Scope) error }
ComparablesConstraint is used to build constraints for generic comparable values validation.
type ConstraintAlreadyStoredError ¶
type ConstraintAlreadyStoredError struct {
Key string
}
ConstraintAlreadyStoredError is returned when trying to put a constraint in the validator store using an existing key.
func (ConstraintAlreadyStoredError) Error ¶
func (err ConstraintAlreadyStoredError) Error() string
type ConstraintError ¶ added in v0.9.0
type ConstraintError struct { ConstraintName string Path *PropertyPath Description string }
ConstraintError is used to return critical error from constraint that immediately stops the validation process. It is recommended to use Scope.NewConstraintError() method to initiate an error from current scope.
func (ConstraintError) Error ¶ added in v0.9.0
func (err ConstraintError) Error() string
type ConstraintNotFoundError ¶
ConstraintNotFoundError is returned when trying to get a constraint from the validator store using a non-existent key.
func (ConstraintNotFoundError) Error ¶
func (err ConstraintNotFoundError) Error() string
type CountableConstraint ¶
CountableConstraint is used to build constraints for simpler validation of iterable elements count.
type CustomStringConstraint ¶ added in v0.2.0
type CustomStringConstraint struct {
// contains filtered or unexported fields
}
CustomStringConstraint can be used to create custom constraints for validating string values based on function with signature func(string) bool.
func NewCustomStringConstraint ¶ added in v0.2.0
func NewCustomStringConstraint(isValid func(string) bool, parameters ...string) CustomStringConstraint
NewCustomStringConstraint creates a new string constraint from a function with signature func(string) bool. Optional parameters can be used to set up violation code (first), message template (second). All other parameters are ignored.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) func main() { validate := func(s string) bool { return s == "valid" } constraint := validation.NewCustomStringConstraint( validate, "exampleCode", // violation code "Unexpected value.", // violation message template ) s := "foo" err := validator.Validate(context.Background(), validation.String(s, constraint)) fmt.Println(err) }
Output: violation: Unexpected value.
func (CustomStringConstraint) Code ¶ added in v0.3.0
func (c CustomStringConstraint) Code(code string) CustomStringConstraint
Code overrides default code for produced violation.
func (CustomStringConstraint) Message ¶ added in v0.2.0
func (c CustomStringConstraint) Message(template string, parameters ...TemplateParameter) CustomStringConstraint
Message sets the violation message template. You can set custom template parameters for injecting its values into the final message. Also, you can use default parameters:
{{ value }} - the current (invalid) value.
func (CustomStringConstraint) ValidateString ¶ added in v0.2.0
func (c CustomStringConstraint) ValidateString(value *string, scope Scope) error
func (CustomStringConstraint) When ¶ added in v0.2.0
func (c CustomStringConstraint) When(condition bool) CustomStringConstraint
When enables conditional validation of this constraint. If the expression evaluates to false, then the constraint will be ignored.
func (CustomStringConstraint) WhenGroups ¶ added in v0.8.0
func (c CustomStringConstraint) WhenGroups(groups ...string) CustomStringConstraint
WhenGroups enables conditional validation of the constraint by using the validation groups.
type NewViolationFunc ¶
type NewViolationFunc func( code, messageTemplate string, pluralCount int, parameters []TemplateParameter, propertyPath *PropertyPath, lang language.Tag, ) Violation
NewViolationFunc is an adapter that allows you to use ordinary functions as a ViolationFactory.
func (NewViolationFunc) CreateViolation ¶
func (f NewViolationFunc) CreateViolation( code, messageTemplate string, pluralCount int, parameters []TemplateParameter, propertyPath *PropertyPath, lang language.Tag, ) Violation
CreateViolation creates a new instance of a Violation.
type NilConstraint ¶
NilConstraint is used for a special cases to check a value for nil.
type NumberConstraint ¶
NumberConstraint is used to build constraints for numeric values validation.
type Numeric ¶ added in v0.9.0
type Numeric interface { ~float32 | ~float64 | ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 }
Numeric is used as a type parameter for numeric values.
type Option ¶
type Option interface { // SetUp is called when the validation process is initialized and can be used to modify scope values. SetUp(scope *Scope) error }
Option is used to set up validation process of a value.
func ArrayIndex ¶
ArrayIndex option adds index of the given array to current validation scope.
func PropertyName ¶
PropertyName option adds name of the given property to current validation scope.
type PropertyNameElement ¶
type PropertyNameElement string
PropertyNameElement holds up property name value under PropertyPath.
func (PropertyNameElement) IsIndex ¶
func (p PropertyNameElement) IsIndex() bool
IsIndex on PropertyNameElement always returns false.
func (PropertyNameElement) String ¶
func (p PropertyNameElement) String() string
String returns property name as is.
type PropertyPath ¶
type PropertyPath struct {
// contains filtered or unexported fields
}
PropertyPath is generated by the validator and indicates how it reached the invalid value from the root element. Property path is denoted by dots, while array access is denoted by square brackets. For example, "book.keywords[0]" means that the violation occurred on the first element of array "keywords" in the "book" object.
Internally PropertyPath is a linked list. You can create a new path using WithProperty or WithIndex methods. PropertyPath should always be used as a pointer value. Nil value is a valid value that means that the property path is empty.
func NewPropertyPath ¶ added in v0.2.0
func NewPropertyPath(elements ...PropertyPathElement) *PropertyPath
NewPropertyPath creates a PropertyPath from the list of elements. If the list is empty nil will be returned. Nil value is a valid value that means that the property path is empty.
func (*PropertyPath) MarshalJSON ¶
func (path *PropertyPath) MarshalJSON() ([]byte, error)
MarshalJSON will marshal property path value to a JSON string.
func (*PropertyPath) String ¶
func (path *PropertyPath) String() string
String is used to format property path to a string.
func (*PropertyPath) WithIndex ¶ added in v0.2.0
func (path *PropertyPath) WithIndex(index int) *PropertyPath
WithIndex returns new PropertyPath with appended ArrayIndexElement to the end of the list.
func (*PropertyPath) WithProperty ¶ added in v0.2.0
func (path *PropertyPath) WithProperty(name string) *PropertyPath
WithProperty returns new PropertyPath with appended PropertyNameElement to the end of the list.
type PropertyPathElement ¶
type PropertyPathElement interface { // IsIndex can be used to determine whether an element is a string (property name) or // an index array. IsIndex() bool fmt.Stringer }
PropertyPathElement is a part of the PropertyPath.
type Scope ¶
type Scope struct {
// contains filtered or unexported fields
}
Scope holds the current state of validation. On the client-side of the package, it can be used to build violations.
func (Scope) AtIndex ¶ added in v0.4.1
AtIndex returns a copy of the scope with property path appended by the given array index.
func (Scope) AtProperty ¶ added in v0.4.1
AtProperty returns a copy of the scope with property path appended by the given property name.
func (Scope) BuildViolation ¶
func (s Scope) BuildViolation(code, message string) *ViolationBuilder
BuildViolation is used to create violations in validation methods of constraints. This method automatically injects the property path and language of the current validation scope.
func (Scope) Context ¶
Context returns context value that was passed to the validator by Context argument or by creating scoped validator with the validator.WithContext method.
func (Scope) IsApplied ¶ added in v0.8.0
IsApplied compares scope validation groups and constraint groups. If one of the scope groups intersects with the constraint groups, the validation scope should be applied (returns true). Empty groups are treated as DefaultGroup. To set validation groups use the validator.WithGroups() method.
func (Scope) IsIgnored ¶ added in v0.8.0
IsIgnored is the reverse condition for applying validation groups to the IsApplied method. It is recommended to use this method in every validation method of the constraint.
func (Scope) NewConstraintError ¶ added in v0.9.0
func (s Scope) NewConstraintError(constraintName, description string) ConstraintError
NewConstraintError creates a new ConstraintError, which can be used to stop validation process if constraint is not properly configured.
func (Scope) Validator ¶ added in v0.3.0
Validator creates a new validator for the given scope. This validator can be used to perform complex validation on a custom constraint using existing constraints.
Example ¶
package main import ( "bytes" "context" "fmt" "path/filepath" "strings" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type File struct { Name string Data []byte } // This validation will always check that file is valid. // Partial validation will be applied by AllowedFileExtensionConstraint // and AllowedFileSizeConstraint. func (f File) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( ctx, validation.StringProperty("name", f.Name, it.HasLengthBetween(5, 50)), ) } type FileUploadRequest struct { Section string File *File } type FileConstraint interface { ValidateFile(file *File, scope validation.Scope) error } func ValidFile(file *File, constraints ...FileConstraint) validation.ValidatorArgument { return validation.NewArgument(func(scope validation.Scope) (*validation.ViolationList, error) { violations := validation.NewViolationList() for _, constraint := range constraints { err := violations.AppendFromError(constraint.ValidateFile(file, scope)) if err != nil { return nil, err } } return violations, nil }) } // AllowedFileExtensionConstraint used to check that file has one of allowed extensions. // This constraint can be used for partial validation. type AllowedFileExtensionConstraint struct { extensions []string } func FileHasAllowedExtension(extensions ...string) AllowedFileExtensionConstraint { return AllowedFileExtensionConstraint{extensions: extensions} } func (c AllowedFileExtensionConstraint) ValidateFile(file *File, scope validation.Scope) error { if file == nil { return nil } extension := strings.ReplaceAll(filepath.Ext(file.Name), ".", "") return scope.Validator().AtProperty("name").Validate( scope.Context(), validation.Comparable[string]( extension, it.IsOneOf(c.extensions...).Message("Not allowed extension. Must be one of: {{ choices }}."), ), ) } // AllowedFileSizeConstraint used to check that file has limited size. // This constraint can be used for partial validation. type AllowedFileSizeConstraint struct { minSize int maxSize int } func FileHasAllowedSize(min, max int) AllowedFileSizeConstraint { return AllowedFileSizeConstraint{minSize: min, maxSize: max} } func (c AllowedFileSizeConstraint) ValidateFile(file *File, scope validation.Scope) error { if file == nil { return nil } size := len(file.Data) return scope.Validator().Validate( scope.Context(), validation.Number[int]( size, it.IsGreaterThan(c.minSize).Message("File size is too small."), it.IsLessThan(c.maxSize).Message("File size is too large."), ), ) } func main() { // this constraints will be applied to all files uploaded as avatars avatarConstraints := []FileConstraint{ FileHasAllowedExtension("jpeg", "jpg", "gif"), FileHasAllowedSize(100, 1000), } // this constraints will be applied to all files uploaded as documents documentConstraints := []FileConstraint{ FileHasAllowedExtension("doc", "pdf", "txt"), FileHasAllowedSize(1000, 100000), } requests := []FileUploadRequest{ { Section: "avatars", File: &File{Name: "avatar.png", Data: bytes.Repeat([]byte{0}, 99)}, }, { Section: "documents", File: &File{Name: "sheet.xls", Data: bytes.Repeat([]byte{0}, 100001)}, }, } for _, request := range requests { switch request.Section { case "avatars": err := validator.Validate( context.Background(), // common validation of validatable validation.Valid(request.File), // specific validation for file storage section ValidFile(request.File, avatarConstraints...), ) fmt.Println(err) case "documents": err := validator.Validate( context.Background(), // common validation of validatable validation.Valid(request.File), // specific validation for file storage section ValidFile(request.File, documentConstraints...), ) fmt.Println(err) } } }
Output: violation at 'name': Not allowed extension. Must be one of: jpeg, jpg, gif.; violation: File size is too small. violation at 'name': Not allowed extension. Must be one of: doc, pdf, txt.; violation: File size is too large.
type SequentialArgument ¶ added in v0.9.0
type SequentialArgument struct {
// contains filtered or unexported fields
}
SequentialArgument can be used to interrupt validation process when the first violation is raised.
func Sequentially ¶ added in v0.2.0
func Sequentially(arguments ...Argument) SequentialArgument
Sequentially function used to run validation process step-by-step.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { title := "bar" err := validator.Validate( context.Background(), validation.Sequentially( validation.String(title, it.IsBlank()), // validation will fail on first argument validation.String(title, it.HasMinLength(5)), // this argument will be ignored ), ) fmt.Println(err) }
Output: violation: This value should be blank.
func (SequentialArgument) When ¶ added in v0.9.0
func (arg SequentialArgument) When(condition bool) SequentialArgument
When enables conditional validation of this argument. If the expression evaluates to false, then the argument will be ignored.
func (SequentialArgument) With ¶ added in v0.9.0
func (arg SequentialArgument) With(options ...Option) SequentialArgument
With returns a copy of SequentialArgument with appended options.
type StringConstraint ¶
StringConstraint is used to build constraints for string values validation.
type TemplateParameter ¶
type TemplateParameter struct { // Key is the marker in the string that will be replaced by value. // In general, it is recommended to use double curly braces around the key name. // Example: {{ keyName }} Key string // Value is set by constraint when building violation. Value string // NeedsTranslation marks that the template value needs to be translated. NeedsTranslation bool }
TemplateParameter is injected into the message while rendering the template.
type TemplateParameterList ¶ added in v0.3.0
type TemplateParameterList []TemplateParameter
TemplateParameterList is a list of template parameters that can be injection into violation message.
func (TemplateParameterList) Prepend ¶ added in v0.3.0
func (params TemplateParameterList) Prepend(parameters ...TemplateParameter) TemplateParameterList
Prepend returns TemplateParameterList prepended by given parameters.
type TimeConstraint ¶
TimeConstraint is used to build constraints for date/time validation.
type Translator ¶
Translator is used to translate violation messages. By default, validator uses an implementation from "github.com/muonsoft/validation/message/translations" package based on "golang.org/x/text" package. You can set up your own implementation by using SetTranslator option.
type Validatable ¶
Validatable is interface for creating validatable types on the client side. By using it you can build complex validation rules on a set of objects used in other objects.
Example
type Book struct { Title string Author string Keywords []string } func (b Book) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( ctx, validation.StringProperty("title", &b.Title, it.IsNotBlank()), validation.StringProperty("author", &b.Author, it.IsNotBlank()), validation.CountableProperty("keywords", len(b.Keywords), it.HasCountBetween(1, 10)), validation.EachStringProperty("keywords", b.Keywords, it.IsNotBlank()), ) }
type ValidateOnScopeFunc ¶ added in v0.9.0
type ValidateOnScopeFunc func(scope Scope) (*ViolationList, error)
type Validator ¶
type Validator struct {
// contains filtered or unexported fields
}
Validator is the main validation service. It can be created by NewValidator constructor. Also, you can use singleton version from the package "github.com/muonsoft/validation/validator".
func NewValidator ¶
func NewValidator(options ...ValidatorOption) (*Validator, error)
NewValidator is a constructor for creating an instance of Validator. You can configure it by using validator options.
Example ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator( validation.DefaultLanguage(language.English), // passing default language of translations validation.Translations(russian.Messages), // setting up custom or built-in translations // validation.SetViolationFactory(userViolationFactory), // if you want to override creation of violations ) // don't forget to check for errors if err != nil { log.Fatal(err) } err = validator.Validate(context.Background(), validation.String("", it.IsNotBlank())) fmt.Println(err) }
Output: violation: This value should not be blank.
func (*Validator) AtIndex ¶
AtIndex method creates a new scoped validator with injected array index element to scope property path.
Example ¶
books := []Book{{Title: ""}} err := validator.AtIndex(0).Validate( context.Background(), validation.StringProperty("title", books[0].Title, it.IsNotBlank()), ) violation := err.(*validation.ViolationList).First() fmt.Println("property path:", violation.PropertyPath().String())
Output: property path: [0].title
func (*Validator) AtProperty ¶
AtProperty method creates a new scoped validator with injected property name element to scope property path.
Example ¶
book := &Book{Title: ""} err := validator.AtProperty("book").Validate( context.Background(), validation.StringProperty("title", book.Title, it.IsNotBlank()), ) violation := err.(*validation.ViolationList).First() fmt.Println("property path:", violation.PropertyPath().String())
Output: property path: book.title
func (*Validator) BuildViolation ¶
func (validator *Validator) BuildViolation(ctx context.Context, code, message string) *ViolationBuilder
BuildViolation can be used to build a custom violation on the client-side.
Example (BuildingViolation) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/validation" ) func main() { validator, err := validation.NewValidator() if err != nil { log.Fatal(err) } violation := validator.BuildViolation(context.Background(), "clientCode", "Client message with {{ parameter }}."). AddParameter("{{ parameter }}", "value"). CreateViolation() fmt.Println(violation.Message()) }
Output: Client message with value.
Example (TranslatableParameter) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "golang.org/x/text/message/catalog" ) func main() { validator, err := validation.NewValidator( validation.Translations(map[language.Tag]map[string]catalog.Message{ language.Russian: { "The operation is only possible for the {{ role }}.": catalog.String("Операция возможна только для {{ role }}."), "administrator role": catalog.String("роли администратора"), }, }), ) if err != nil { log.Fatal(err) } violation := validator.WithLanguage(language.Russian). BuildViolation(context.Background(), "clientCode", "The operation is only possible for the {{ role }}."). SetParameters(validation.TemplateParameter{ Key: "{{ role }}", Value: "administrator role", NeedsTranslation: true, }). CreateViolation() fmt.Println(violation.Message()) }
Output: Операция возможна только для роли администратора.
func (*Validator) GetConstraint ¶ added in v0.9.0
GetConstraint is used to get the constraint from the internal validator store. If the constraint does not exist, then the validator will return nil. For storing a constraint you should use the StoredConstraint option.
Experimental. This feature is experimental and may be changed in future versions.
Example (CustomServiceConstraint) ¶
package main import ( "context" "errors" "fmt" "log" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" ) type contextKey string const exampleKey contextKey = "exampleKey" type TagStorage struct { // this might be stored in the database tags []string } func (storage *TagStorage) FindByName(ctx context.Context, name string) ([]string, error) { contextValue, ok := ctx.Value(exampleKey).(string) if !ok { return nil, errors.New("context value missing") } if contextValue != "value" { return nil, errors.New("invalid context value") } found := make([]string, 0) for _, tag := range storage.tags { if tag == name { found = append(found, tag) } } return found, nil } type ExistingTagConstraint struct { storage *TagStorage } func (c *ExistingTagConstraint) SetUp() error { return nil } func (c *ExistingTagConstraint) Name() string { return "ExistingTagConstraint" } func (c *ExistingTagConstraint) ValidateString(value *string, scope validation.Scope) error { // usually, you should ignore empty values // to check for an empty value you should use it.NotBlankConstraint if value == nil || *value == "" { return nil } // you can pass the context value from the scope entities, err := c.storage.FindByName(scope.Context(), *value) // here you can return a service error so that the validation process // is stopped immediately if err != nil { return err } if len(entities) > 0 { return nil } // use the scope to build violation with translations return scope. BuildViolation("unknownTag", `Tag "{{ value }}" does not exist.`). // you can inject parameter value to the message here AddParameter("{{ value }}", *value). CreateViolation() } type StockItem struct { Name string Tags []string } func (s StockItem) Validate(ctx context.Context, validator *validation.Validator) error { isTagExists, ok := validator.GetConstraint("isTagExists").(validation.StringConstraint) if !ok { return validation.ConstraintNotFoundError{Key: "isTagExists", Type: "validation.StringConstraint"} } return validator.Validate( ctx, validation.StringProperty("name", s.Name, it.IsNotBlank(), it.HasMaxLength(20)), validation.EachStringProperty("tags", s.Tags, isTagExists), ) } func main() { storage := &TagStorage{tags: []string{"movie", "book"}} isTagExists := &ExistingTagConstraint{storage: storage} // custom constraint can be stored in the validator's internal store // and can be used later by calling the validator.GetConstraint method validator, err := validation.NewValidator( validation.StoredConstraint("isTagExists", isTagExists), ) if err != nil { log.Fatal(err) } item := StockItem{ Name: "War and peace", Tags: []string{"book", "camera"}, } err = validator.Validate( // you can pass here the context value to the validation scope context.WithValue(context.Background(), exampleKey, "value"), validation.Valid(item), ) fmt.Println(err) }
Output: violation at 'tags[1]': Tag "camera" does not exist.
func (*Validator) Validate ¶
Validate is the main validation method. It accepts validation arguments. executionContext can be used to tune up the validation process or to pass values of a specific type.
Example (BasicStructValidation) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { document := struct { Title string Keywords []string }{ Title: "", Keywords: []string{"", "book", "fantasy", "book"}, } err := validator.Validate( context.Background(), validation.StringProperty("title", document.Title, it.IsNotBlank()), validation.CountableProperty("keywords", len(document.Keywords), it.HasCountBetween(5, 10)), validation.ComparablesProperty[string]("keywords", document.Keywords, it.HasUniqueValues[string]()), validation.EachStringProperty("keywords", document.Keywords, it.IsNotBlank()), ) if violations, ok := validation.UnwrapViolationList(err); ok { for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } }
Output: violation at 'title': This value should not be blank. violation at 'keywords': This collection should contain 5 elements or more. violation at 'keywords': This collection should contain only unique elements. violation at 'keywords[0]': This value should not be blank.
Example (BasicValidation) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" ) func main() { s := "" validator, err := validation.NewValidator() if err != nil { log.Fatal(err) } err = validator.Validate(context.Background(), validation.String(s, it.IsNotBlank())) fmt.Println(err) }
Output: violation: This value should not be blank.
Example (ConditionalValidationOnConstraint) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { notes := []struct { Title string IsPublic bool Text string }{ {Title: "published note", IsPublic: true, Text: "text of published note"}, {Title: "draft note", IsPublic: true, Text: ""}, } for i, note := range notes { err := validator.Validate( context.Background(), validation.StringProperty("name", note.Title, it.IsNotBlank()), validation.StringProperty("text", note.Text, it.IsNotBlank().When(note.IsPublic)), ) if violations, ok := validation.UnwrapViolationList(err); ok { for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Printf("error on note %d: %s", i, violation) } } } }
Output: error on note 1: violation at 'text': This value should not be blank.
Example (CustomConstraint) ¶
package main import ( "context" "fmt" "regexp" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type NumericConstraint struct { matcher *regexp.Regexp } // it is recommended to use semantic constructors for constraints. func IsNumeric() NumericConstraint { return NumericConstraint{matcher: regexp.MustCompile("^[0-9]+$")} } func (c NumericConstraint) SetUp() error { // you may return errors here on the constraint initialization process return nil } func (c NumericConstraint) Name() string { return "NumericConstraint" } func (c NumericConstraint) ValidateString(value *string, scope validation.Scope) error { // usually, you should ignore empty values // to check for an empty value you should use it.NotBlankConstraint if value == nil || *value == "" { return nil } if c.matcher.MatchString(*value) { return nil } // use the scope to build violation with translations return scope.BuildViolation("notNumeric", "This value should be numeric.").CreateViolation() } func main() { s := "alpha" err := validator.Validate( context.Background(), validation.String(s, it.IsNotBlank(), IsNumeric()), ) fmt.Println(err) }
Output: violation: This value should be numeric.
Example (CustomizingErrorMessage) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := "" err := validator.Validate( context.Background(), validation.String(s, it.IsNotBlank().Message("this value is required")), ) fmt.Println(err) }
Output: violation: this value is required
Example (HttpHandler) ¶
package main import ( "context" "encoding/json" "fmt" "log" "net/http" "net/http/httptest" "strings" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) type Book struct { Title string `json:"title"` Author string `json:"author"` Keywords []string `json:"keywords"` } func (b Book) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( ctx, validation.StringProperty("title", b.Title, it.IsNotBlank()), validation.StringProperty("author", b.Author, it.IsNotBlank()), validation.CountableProperty("keywords", len(b.Keywords), it.HasCountBetween(1, 10)), validation.EachStringProperty("keywords", b.Keywords, it.IsNotBlank()), ) } func HandleBooks(writer http.ResponseWriter, request *http.Request) { var book Book err := json.NewDecoder(request.Body).Decode(&book) if err != nil { http.Error(writer, "invalid request", http.StatusBadRequest) return } // setting up validator validator, err := validation.NewValidator(validation.Translations(russian.Messages)) if err != nil { http.Error(writer, err.Error(), http.StatusInternalServerError) return } err = validator.Validate(request.Context(), validation.Valid(book)) if err != nil { violations, ok := validation.UnwrapViolationList(err) if ok { response, err := json.Marshal(violations) if err != nil { log.Fatal(err) } writer.WriteHeader(http.StatusUnprocessableEntity) writer.Header().Set("Content-Type", "application/json") writer.Write(response) return } http.Error(writer, err.Error(), http.StatusInternalServerError) return } // handle valid book writer.WriteHeader(http.StatusCreated) writer.Write([]byte("ok")) } func main() { var handler http.Handler handler = http.HandlerFunc(HandleBooks) // middleware set up: we need to set supported languages // detected language will be passed via request context handler = language.NewMiddleware(handler, language.SupportedLanguages(language.English, language.Russian)) // creating request with the language-specific header request := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(`{}`)) request.Header.Set("Accept-Language", "ru") recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, request) // recorded response should contain array of violations fmt.Println(recorder.Body.String()) }
Output: [{"code":"notBlank","message":"Значение не должно быть пустым.","propertyPath":"title"},{"code":"notBlank","message":"Значение не должно быть пустым.","propertyPath":"author"},{"code":"countTooFew","message":"Эта коллекция должна содержать 1 элемент или больше.","propertyPath":"keywords"}]
Example (PassingPropertyPathViaOptions) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := "" err := validator.Validate( context.Background(), validation.String(s, it.IsNotBlank()).With( validation.PropertyName("properties"), validation.ArrayIndex(1), validation.PropertyName("tag"), ), ) violation := err.(*validation.ViolationList).First() fmt.Println("property path:", violation.PropertyPath().String()) }
Output: property path: properties[1].tag
Example (PropertyPathBySpecialArgument) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := "" err := validator.Validate( context.Background(), // this is an alias for // validation.String(&s, validation.PropertyName("property"), it.IsNotBlank()), validation.StringProperty("property", s, it.IsNotBlank()), ) violation := err.(*validation.ViolationList).First() fmt.Println("property path:", violation.PropertyPath().String()) }
Output: property path: property
Example (PropertyPathWithScopedValidator) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := "" err := validator. AtProperty("properties"). AtIndex(1). AtProperty("tag"). Validate(context.Background(), validation.String(s, it.IsNotBlank())) violation := err.(*validation.ViolationList).First() fmt.Println("property path:", violation.PropertyPath().String()) }
Output: property path: properties[1].tag
Example (SingletonValidator) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := "" err := validator.Validate(context.Background(), validation.String(s, it.IsNotBlank())) fmt.Println(err) }
Output: violation: This value should not be blank.
Example (TranslationForCustomMessage) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "golang.org/x/text/feature/plural" "golang.org/x/text/message/catalog" ) func main() { const customMessage = "tags should contain more than {{ limit }} element(s)" validator, err := validation.NewValidator( validation.Translations(map[language.Tag]map[string]catalog.Message{ language.Russian: { customMessage: plural.Selectf(1, "", plural.One, "теги должны содержать {{ limit }} элемент и более", plural.Few, "теги должны содержать более {{ limit }} элемента", plural.Other, "теги должны содержать более {{ limit }} элементов"), }, }), ) if err != nil { log.Fatal(err) } var tags []string err = validator.Validate( context.Background(), validation.Language(language.Russian), validation.Countable(len(tags), it.HasMinCount(1).MinMessage(customMessage)), ) fmt.Println(err) }
Output: violation: теги должны содержать 1 элемент и более
Example (TranslationsByArgument) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator( validation.Translations(russian.Messages), ) if err != nil { log.Fatal(err) } s := "" err = validator.Validate( context.Background(), validation.Language(language.Russian), validation.String(s, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: Значение не должно быть пустым.
Example (TranslationsByContextArgument) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator( validation.Translations(russian.Messages), ) if err != nil { log.Fatal(err) } s := "" ctx := language.WithContext(context.Background(), language.Russian) err = validator.Validate( ctx, validation.String(s, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: Значение не должно быть пустым.
Example (TranslationsByDefaultLanguage) ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator( validation.Translations(russian.Messages), validation.DefaultLanguage(language.Russian), ) if err != nil { log.Fatal(err) } s := "" err = validator.Validate(context.Background(), validation.String(s, it.IsNotBlank())) fmt.Println(err) }
Output: violation: Значение не должно быть пустым.
Example (UsingContextWithRecursion) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) // It is recommended to make a custom constraint to check for nesting limit. type NestingLimitConstraint struct { limit int } func (c NestingLimitConstraint) SetUp() error { return nil } func (c NestingLimitConstraint) Name() string { return "NestingLimitConstraint" } func (c NestingLimitConstraint) ValidateProperty(property *Property, scope validation.Scope) error { // You can read any passed context value from scope. level, ok := scope.Context().Value(nestingLevelKey).(int) if !ok { // Don't forget to handle missing value. return fmt.Errorf("nesting level not found in context") } if level >= c.limit { return scope. BuildViolation("nestingLimitReached", "Maximum nesting level reached."). CreateViolation() } return nil } func ItIsNotDeeperThan(limit int) NestingLimitConstraint { return NestingLimitConstraint{limit: limit} } // Properties can be nested. type Property struct { Name string Properties []Property } // You can declare you own constraint interface to create custom constraints. type PropertyConstraint interface { ValidateProperty(property *Property, scope validation.Scope) error } // To create your own functional argument for validation simply create a function with // a typed value and use the validation.NewArgument constructor. func ValidProperty(property *Property, constraints ...PropertyConstraint) validation.ValidatorArgument { return validation.NewArgument(func(scope validation.Scope) (*validation.ViolationList, error) { violations := validation.NewViolationList() for i := range constraints { err := violations.AppendFromError(constraints[i].ValidateProperty(property, scope)) if err != nil { return nil, err } } return violations, nil }) } type recursionKey string const nestingLevelKey recursionKey = "nestingLevel" func (p Property) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( // Incrementing nesting level in context with special function. contextWithNextNestingLevel(ctx), // Executing validation for maximum nesting level of properties. ValidProperty(&p, ItIsNotDeeperThan(3)), validation.StringProperty("name", p.Name, it.IsNotBlank()), // This should run recursive validation for properties. validation.ValidSliceProperty("properties", p.Properties), ) } // This function increments current nesting level. func contextWithNextNestingLevel(ctx context.Context) context.Context { level, ok := ctx.Value(nestingLevelKey).(int) if !ok { level = -1 } return context.WithValue(ctx, nestingLevelKey, level+1) } func main() { properties := []Property{ { Name: "top", Properties: []Property{ { Name: "middle", Properties: []Property{ { Name: "low", Properties: []Property{ // This property should cause a violation. {Name: "limited"}, }, }, }, }, }, }, } err := validator.Validate(context.Background(), validation.ValidSlice(properties)) fmt.Println(err) }
Output: violation at '[0].properties[0].properties[0].properties[0]': Maximum nesting level reached.
func (*Validator) ValidateBool ¶
func (validator *Validator) ValidateBool(ctx context.Context, value bool, constraints ...BoolConstraint) error
ValidateBool is an alias for validating a single boolean value.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := false err := validator.ValidateBool(context.Background(), v, it.IsTrue()) fmt.Println(err) }
Output: violation: This value should be true.
func (*Validator) ValidateCountable ¶
func (validator *Validator) ValidateCountable(ctx context.Context, count int, constraints ...CountableConstraint) error
ValidateCountable is an alias for validating a single countable value (an array, slice, or map).
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := []string{"a", "b"} err := validator.ValidateCountable(context.Background(), len(s), it.HasMinCount(3)) fmt.Println(err) }
Output: violation: This collection should contain 3 elements or more.
func (*Validator) ValidateEachString ¶
func (validator *Validator) ValidateEachString(ctx context.Context, values []string, constraints ...StringConstraint) error
ValidateEachString is an alias for validating each value of a strings slice.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := []string{""} err := validator.ValidateEachString(context.Background(), v, it.IsNotBlank()) fmt.Println(err) }
Output: violation at '[0]': This value should not be blank.
func (*Validator) ValidateFloat ¶ added in v0.9.0
func (validator *Validator) ValidateFloat(ctx context.Context, value float64, constraints ...NumberConstraint[float64]) error
ValidateFloat is an alias for validating a single float value.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 5.5 err := validator.ValidateFloat(context.Background(), v, it.IsGreaterThan(6.5)) fmt.Println(err) }
Output: violation: This value should be greater than 6.5.
func (*Validator) ValidateInt ¶ added in v0.9.0
func (validator *Validator) ValidateInt(ctx context.Context, value int, constraints ...NumberConstraint[int]) error
ValidateInt is an alias for validating a single integer value.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 5 err := validator.ValidateInt(context.Background(), v, it.IsGreaterThan(5)) fmt.Println(err) }
Output: violation: This value should be greater than 5.
func (*Validator) ValidateIt ¶ added in v0.9.0
func (validator *Validator) ValidateIt(ctx context.Context, validatable Validatable) error
ValidateIt is an alias for validating value that implements the Validatable interface.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type Person struct { Name string Surname string Age int } func (p Person) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate(ctx, validation.StringProperty("name", p.Name, it.IsNotBlank(), it.HasMaxLength(50)), validation.StringProperty("surname", p.Surname, it.IsNotBlank(), it.HasMaxLength(100)), validation.NumberProperty[int]("age", p.Age, it.IsBetween(18, 100)), ) } func main() { persons := []Person{ { Name: "John", Surname: "Doe", Age: 23, }, { Name: "", Surname: "", Age: 0, }, } for i, person := range persons { err := validator.ValidateIt(context.Background(), person) if violations, ok := validation.UnwrapViolationList(err); ok { fmt.Println("person", i, "is not valid:") for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } } }
Output: person 1 is not valid: violation at 'name': This value should not be blank. violation at 'surname': This value should not be blank. violation at 'age': This value should be between 18 and 100.
func (*Validator) ValidateString ¶
func (validator *Validator) ValidateString(ctx context.Context, value string, constraints ...StringConstraint) error
ValidateString is an alias for validating a single string value.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { err := validator.ValidateString(context.Background(), "", it.IsNotBlank()) fmt.Println(err) }
Output: violation: This value should not be blank.
func (*Validator) ValidateStrings ¶ added in v0.4.0
func (validator *Validator) ValidateStrings(ctx context.Context, values []string, constraints ...ComparablesConstraint[string]) error
ValidateStrings is an alias for validating slice of strings.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := []string{"foo", "bar", "baz", "foo"} err := validator.ValidateStrings(context.Background(), v, it.HasUniqueValues[string]()) fmt.Println(err) }
Output: violation: This collection should contain only unique elements.
func (*Validator) ValidateTime ¶
func (validator *Validator) ValidateTime(ctx context.Context, value time.Time, constraints ...TimeConstraint) error
ValidateTime is an alias for validating a single time value.
Example ¶
package main import ( "context" "fmt" "time" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { t := time.Now() compared, _ := time.Parse(time.RFC3339, "2006-01-02T15:00:00Z") err := validator.ValidateTime(context.Background(), t, it.IsEarlierThan(compared)) fmt.Println(err) }
Output: violation: This value should be earlier than 2006-01-02T15:00:00Z.
func (*Validator) WithGroups ¶ added in v0.8.0
WithGroups is used to execute conditional validation based on validation groups. It creates a new scoped validation with a given set of groups.
By default, when validating an object all constraints of it will be checked whether or not they pass. In some cases, however, you will need to validate an object against only some specific group of constraints. To do this, you can organize each constraint into one or more validation groups and then apply validation against one group of constraints.
Validation groups are working together only with validation groups passed to a constraint by WhenGroups() method. This method is implemented in all built-in constraints. If you want to use validation groups for your own constraints do not forget to implement this method in your constraint.
Be careful, empty groups are considered as the default group. Its value is equal to the DefaultGroup ("default").
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type User struct { Email string Password string City string } func (u User) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( ctx, validation.StringProperty( "email", u.Email, it.IsNotBlank().WhenGroups("registration"), it.IsEmail().WhenGroups("registration"), ), validation.StringProperty( "password", u.Password, it.IsNotBlank().WhenGroups("registration"), it.HasMinLength(7).WhenGroups("registration"), ), validation.StringProperty( "city", u.City, it.HasMinLength(2), // this constraint belongs to the default group ), ) } func main() { user := User{ Email: "invalid email", Password: "1234", City: "Z", } err1 := validator.WithGroups("registration").Validate(context.Background(), validation.Valid(user)) err2 := validator.Validate(context.Background(), validation.Valid(user)) if violations, ok := validation.UnwrapViolationList(err1); ok { fmt.Println("violations for registration group:") for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } if violations, ok := validation.UnwrapViolationList(err2); ok { fmt.Println("violations for default group:") for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } }
Output: violations for registration group: violation at 'email': This value is not a valid email address. violation at 'password': This value is too short. It should have 7 characters or more. violations for default group: violation at 'city': This value is too short. It should have 2 characters or more.
func (*Validator) WithLanguage ¶
WithLanguage method creates a new scoped validator with a given language tag. All created violations will be translated into this language.
Example ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator(validation.Translations(russian.Messages)) if err != nil { log.Fatal(err) } s := "" err = validator.WithLanguage(language.Russian).Validate( context.Background(), validation.String(s, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: Значение не должно быть пустым.
type ValidatorArgument ¶ added in v0.9.0
type ValidatorArgument struct {
// contains filtered or unexported fields
}
ValidatorArgument is common implementation of Argument that is used to run validation process on given argument.
func Bool ¶
func Bool(value bool, constraints ...BoolConstraint) ValidatorArgument
Bool argument is used to validate boolean values.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := false err := validator.Validate(context.Background(), validation.Bool(v, it.IsTrue())) fmt.Println(err) }
Output: violation: This value should be true.
func BoolProperty ¶
func BoolProperty(name string, value bool, constraints ...BoolConstraint) ValidatorArgument
BoolProperty argument is an alias for Bool that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { IsPublished bool }{ IsPublished: false, } err := validator.Validate( context.Background(), validation.BoolProperty("isPublished", v.IsPublished, it.IsTrue()), ) fmt.Println(err) }
Output: violation at 'isPublished': This value should be true.
func CheckNoViolations ¶ added in v0.7.0
func CheckNoViolations(err error) ValidatorArgument
CheckNoViolations is a special argument that checks err for violations. If err contains Violation or ViolationList then these violations will be appended into returned violation list from the validator. If err contains an error that does not implement an error interface, then the validation process will be terminated and this error will be returned.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type Vehicle struct { Model string MaxSpeed int } func (v Vehicle) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate(ctx, validation.StringProperty("model", v.Model, it.IsNotBlank(), it.HasMaxLength(100)), validation.NumberProperty[int]("maxSpeed", v.MaxSpeed, it.IsBetween(50, 200)), ) } type Car struct { Vehicle PassengerSeats int } func (c Car) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate(ctx, validation.CheckNoViolations(c.Vehicle.Validate(ctx, validator)), validation.NumberProperty[int]("passengerSeats", c.PassengerSeats, it.IsBetween(2, 6)), ) } type Truck struct { Vehicle LoadCapacity float64 } func (t Truck) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate(ctx, validation.CheckNoViolations(t.Vehicle.Validate(ctx, validator)), validation.NumberProperty[float64]("loadCapacity", t.LoadCapacity, it.IsBetween(10.0, 200.0)), ) } func main() { vehicles := []validation.Validatable{ Car{ Vehicle: Vehicle{ Model: "Audi", MaxSpeed: 10, }, PassengerSeats: 1, }, Truck{ Vehicle: Vehicle{ Model: "Benz", MaxSpeed: 20, }, LoadCapacity: 5, }, } for i, vehicle := range vehicles { err := validator.ValidateIt(context.Background(), vehicle) if violations, ok := validation.UnwrapViolationList(err); ok { fmt.Println("vehicle", i, "is not valid:") for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } } }
Output: vehicle 0 is not valid: violation at 'maxSpeed': This value should be between 50 and 200. violation at 'passengerSeats': This value should be between 2 and 6. vehicle 1 is not valid: violation at 'maxSpeed': This value should be between 50 and 200. violation at 'loadCapacity': This value should be between 10 and 200.
func Comparable ¶ added in v0.9.0
func Comparable[T comparable](value T, constraints ...ComparableConstraint[T]) ValidatorArgument
Comparable argument is used to validate generic comparable value.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 4 err := validator.Validate( context.Background(), validation.Comparable[int](v, it.IsOneOf(1, 2, 3, 5)), ) fmt.Println(err) }
Output: violation: The value you selected is not a valid choice.
Example (String) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := "unknown" err := validator.Validate( context.Background(), validation.Comparable[string](v, it.IsOneOf("foo", "bar", "baz")), ) fmt.Println(err) }
Output: violation: The value you selected is not a valid choice.
func ComparableProperty ¶ added in v0.9.0
func ComparableProperty[T comparable](name string, value T, constraints ...ComparableConstraint[T]) ValidatorArgument
ComparableProperty argument is an alias for Comparable that automatically adds property name to the current scope.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := struct { Metric int }{ Metric: 4, } err := validator.Validate( context.Background(), validation.ComparableProperty[int]("metric", s.Metric, it.IsOneOf(1, 2, 3, 5)), ) fmt.Println(err) }
Output: violation at 'metric': The value you selected is not a valid choice.
Example (String) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := struct { Enum string }{ Enum: "unknown", } err := validator.Validate( context.Background(), validation.ComparableProperty[string]("enum", s.Enum, it.IsOneOf("foo", "bar", "baz")), ) fmt.Println(err) }
Output: violation at 'enum': The value you selected is not a valid choice.
func Comparables ¶ added in v0.9.0
func Comparables[T comparable](values []T, constraints ...ComparablesConstraint[T]) ValidatorArgument
Comparables argument is used to validate generic comparable types.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := []string{"foo", "bar", "baz", "foo"} err := validator.Validate( context.Background(), validation.Comparables[string](v, it.HasUniqueValues[string]()), ) fmt.Println(err) }
Output: violation: This collection should contain only unique elements.
func ComparablesProperty ¶ added in v0.9.0
func ComparablesProperty[T comparable](name string, values []T, constraints ...ComparablesConstraint[T]) ValidatorArgument
ComparablesProperty argument is an alias for Comparables that automatically adds property name to the current scope.
Example ¶
v := Book{Keywords: []string{"foo", "bar", "baz", "foo"}} err := validator.Validate( context.Background(), validation.ComparablesProperty[string]("keywords", v.Keywords, it.HasUniqueValues[string]()), ) fmt.Println(err)
Output: violation at 'keywords': This collection should contain only unique elements.
func Countable ¶
func Countable(count int, constraints ...CountableConstraint) ValidatorArgument
Countable argument can be used to validate size of an array, slice, or map. You can pass result of len() function as an argument.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := []string{"a", "b"} err := validator.Validate( context.Background(), validation.Countable(len(s), it.HasMinCount(3)), ) fmt.Println(err) }
Output: violation: This collection should contain 3 elements or more.
func CountableProperty ¶
func CountableProperty(name string, count int, constraints ...CountableConstraint) ValidatorArgument
CountableProperty argument is an alias for Countable that automatically adds property name to the current scope.
Example ¶
v := Product{Tags: []string{"a", "b"}} err := validator.Validate( context.Background(), validation.CountableProperty("tags", len(v.Tags), it.HasMinCount(3)), ) fmt.Println(err)
Output: violation at 'tags': This collection should contain 3 elements or more.
func EachComparable ¶ added in v0.9.0
func EachComparable[T comparable](values []T, constraints ...ComparableConstraint[T]) ValidatorArgument
EachComparable is used to validate a slice of generic comparables.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := []string{"foo", "bar", "baz"} err := validator.Validate( context.Background(), validation.EachComparable[string](v, it.IsOneOf("foo", "bar", "buz")), ) fmt.Println(err) }
Output: violation at '[2]': The value you selected is not a valid choice.
func EachComparableProperty ¶ added in v0.9.0
func EachComparableProperty[T comparable](name string, values []T, constraints ...ComparableConstraint[T]) ValidatorArgument
EachComparableProperty argument is an alias for EachComparable that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Labels []string }{ Labels: []string{"foo", "bar", "baz"}, } err := validator.Validate( context.Background(), validation.EachComparableProperty[string]("labels", v.Labels, it.IsOneOf("foo", "bar", "buz")), ) fmt.Println(err) }
Output: violation at 'labels[2]': The value you selected is not a valid choice.
func EachNumber ¶ added in v0.9.0
func EachNumber[T Numeric](values []T, constraints ...NumberConstraint[T]) ValidatorArgument
EachNumber is used to validate a slice of numbers.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := []int{-1, 0, 1} err := validator.Validate( context.Background(), validation.EachNumber[int](v, it.IsPositiveOrZero[int]()), ) fmt.Println(err) }
Output: violation at '[0]': This value should be either positive or zero.
func EachNumberProperty ¶ added in v0.9.0
func EachNumberProperty[T Numeric](name string, values []T, constraints ...NumberConstraint[T]) ValidatorArgument
EachNumberProperty argument is an alias for EachString that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Metrics []int }{ Metrics: []int{-1, 0, 1}, } err := validator.Validate( context.Background(), validation.EachNumberProperty[int]("metrics", v.Metrics, it.IsPositiveOrZero[int]()), ) fmt.Println(err) }
Output: violation at 'metrics[0]': This value should be either positive or zero.
func EachString ¶
func EachString(values []string, constraints ...StringConstraint) ValidatorArgument
EachString is used to validate a slice of strings.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := []string{""} err := validator.Validate( context.Background(), validation.EachString(v, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation at '[0]': This value should not be blank.
func EachStringProperty ¶
func EachStringProperty(name string, values []string, constraints ...StringConstraint) ValidatorArgument
EachStringProperty argument is an alias for EachString that automatically adds property name to the current scope.
Example ¶
v := Product{Tags: []string{""}} err := validator.Validate( context.Background(), validation.EachStringProperty("tags", v.Tags, it.IsNotBlank()), ) fmt.Println(err)
Output: violation at 'tags[0]': This value should not be blank.
func NewArgument ¶
func NewArgument(validate ValidateOnScopeFunc) ValidatorArgument
NewArgument can be used to implement validation functional arguments for the specific types.
Example (CustomArgumentConstraintValidator) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) type Brand struct { Name string } type BrandRepository struct { brands []Brand } func (repository *BrandRepository) FindByName(ctx context.Context, name string) ([]Brand, error) { found := make([]Brand, 0) for _, brand := range repository.brands { if brand.Name == name { found = append(found, brand) } } return found, nil } // You can declare you own constraint interface to create custom constraints. type BrandConstraint interface { ValidateBrand(brand *Brand, scope validation.Scope) error } // To create your own functional argument for validation simply create a function with // a typed value and use the validation.NewArgument constructor. func ValidBrand(brand *Brand, constraints ...BrandConstraint) validation.ValidatorArgument { return validation.NewArgument(func(scope validation.Scope) (*validation.ViolationList, error) { violations := validation.NewViolationList() for i := range constraints { err := violations.AppendFromError(constraints[i].ValidateBrand(brand, scope)) if err != nil { return nil, err } } return violations, nil }) } // UniqueBrandConstraint implements BrandConstraint. type UniqueBrandConstraint struct { brands *BrandRepository } func (c *UniqueBrandConstraint) SetUp() error { return nil } func (c *UniqueBrandConstraint) Name() string { return "UniqueBrandConstraint" } func (c *UniqueBrandConstraint) ValidateBrand(brand *Brand, scope validation.Scope) error { // usually, you should ignore empty values // to check for an empty value you should use it.NotBlankConstraint if brand == nil { return nil } // you can pass the context value from the scope brands, err := c.brands.FindByName(scope.Context(), brand.Name) // here you can return a service error so that the validation process // is stopped immediately if err != nil { return err } if len(brands) == 0 { return nil } // use the scope to build violation with translations return scope. BuildViolation("notUniqueBrand", `Brand with name "{{ name }}" already exists.`). // you can inject parameter value to the message here AddParameter("{{ name }}", brand.Name). CreateViolation() } func main() { repository := &BrandRepository{brands: []Brand{{"Apple"}, {"Orange"}}} isEntityUnique := &UniqueBrandConstraint{brands: repository} brand := Brand{Name: "Apple"} err := validator.Validate( // you can pass here the context value to the validation scope context.WithValue(context.Background(), exampleKey, "value"), ValidBrand(&brand, isEntityUnique), ) fmt.Println(err) }
Output: violation: Brand with name "Apple" already exists.
func Nil ¶ added in v0.9.0
func Nil(isNil bool, constraints ...NilConstraint) ValidatorArgument
Nil argument is used to validate nil values of any nillable types.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { var v []string err := validator.Validate(context.Background(), validation.Nil(v == nil, it.IsNotNil())) fmt.Println(err) }
Output: violation: This value should not be nil.
func NilBool ¶ added in v0.5.0
func NilBool(value *bool, constraints ...BoolConstraint) ValidatorArgument
NilBool argument is used to validate nillable boolean values.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := false err := validator.Validate(context.Background(), validation.NilBool(&v, it.IsTrue())) fmt.Println(err) }
Output: violation: This value should be true.
func NilBoolProperty ¶ added in v0.5.0
func NilBoolProperty(name string, value *bool, constraints ...BoolConstraint) ValidatorArgument
NilBoolProperty argument is an alias for NilBool that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { IsPublished bool }{ IsPublished: false, } err := validator.Validate( context.Background(), validation.NilBoolProperty("isPublished", &v.IsPublished, it.IsTrue()), ) fmt.Println(err) }
Output: violation at 'isPublished': This value should be true.
func NilComparable ¶ added in v0.9.0
func NilComparable[T comparable](value *T, constraints ...ComparableConstraint[T]) ValidatorArgument
NilComparable argument is used to validate nillable generic comparable value.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 4 err := validator.Validate( context.Background(), validation.NilComparable[int](&v, it.IsOneOf(1, 2, 3, 5)), ) fmt.Println(err) }
Output: violation: The value you selected is not a valid choice.
Example (String) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := "unknown" err := validator.Validate( context.Background(), validation.NilComparable[string](&v, it.IsOneOf("foo", "bar", "baz")), ) fmt.Println(err) }
Output: violation: The value you selected is not a valid choice.
func NilComparableProperty ¶ added in v0.9.0
func NilComparableProperty[T comparable](name string, value *T, constraints ...ComparableConstraint[T]) ValidatorArgument
NilComparableProperty argument is an alias for NilComparable that automatically adds property name to the current scope.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := struct { Metric int }{ Metric: 4, } err := validator.Validate( context.Background(), validation.NilComparableProperty[int]("metric", &s.Metric, it.IsOneOf(1, 2, 3, 5)), ) fmt.Println(err) }
Output: violation at 'metric': The value you selected is not a valid choice.
Example (String) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { s := struct { Enum string }{ Enum: "unknown", } err := validator.Validate( context.Background(), validation.NilComparableProperty[string]("enum", &s.Enum, it.IsOneOf("foo", "bar", "baz")), ) fmt.Println(err) }
Output: violation at 'enum': The value you selected is not a valid choice.
func NilNumber ¶ added in v0.9.0
func NilNumber[T Numeric](value *T, constraints ...NumberConstraint[T]) ValidatorArgument
NilNumber argument is used to validate nillable numbers.
Example (Float) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 5.5 err := validator.Validate( context.Background(), validation.NilNumber[float64](&v, it.IsGreaterThan(6.5)), ) fmt.Println(err) }
Output: violation: This value should be greater than 6.5.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 5 err := validator.Validate( context.Background(), validation.NilNumber[int](&v, it.IsGreaterThan(5)), ) fmt.Println(err) }
Output: violation: This value should be greater than 5.
func NilNumberProperty ¶ added in v0.9.0
func NilNumberProperty[T Numeric](name string, value *T, constraints ...NumberConstraint[T]) ValidatorArgument
NilNumberProperty argument is an alias for NilNumber that automatically adds property name to the current scope.
Example (Float) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Amount float64 }{ Amount: 5.5, } err := validator.Validate( context.Background(), validation.NilNumberProperty[float64]("amount", &v.Amount, it.IsGreaterThan(6.5)), ) fmt.Println(err) }
Output: violation at 'amount': This value should be greater than 6.5.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Count int }{ Count: 5, } err := validator.Validate( context.Background(), validation.NilNumberProperty[int]("count", &v.Count, it.IsGreaterThan(5)), ) fmt.Println(err) }
Output: violation at 'count': This value should be greater than 5.
func NilProperty ¶ added in v0.9.0
func NilProperty(name string, isNil bool, constraints ...NilConstraint) ValidatorArgument
NilProperty argument is an alias for Nil that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Tags []string }{} err := validator.Validate(context.Background(), validation.NilProperty("tags", v.Tags == nil, it.IsNotNil())) fmt.Println(err) }
Output: violation at 'tags': This value should not be nil.
func NilString ¶ added in v0.5.0
func NilString(value *string, constraints ...StringConstraint) ValidatorArgument
NilString argument is used to validate nillable strings.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := "" err := validator.Validate( context.Background(), validation.NilString(&v, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: This value should not be blank.
func NilStringProperty ¶ added in v0.5.0
func NilStringProperty(name string, value *string, constraints ...StringConstraint) ValidatorArgument
NilStringProperty argument is an alias for NilString that automatically adds property name to the current scope.
Example ¶
v := Book{Title: ""} err := validator.Validate( context.Background(), validation.NilStringProperty("title", &v.Title, it.IsNotBlank()), ) fmt.Println(err)
Output: violation at 'title': This value should not be blank.
func NilTime ¶ added in v0.5.0
func NilTime(value *time.Time, constraints ...TimeConstraint) ValidatorArgument
NilTime argument is used to validate nillable time.Time value.
Example ¶
package main import ( "context" "fmt" "time" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { t := time.Now() compared, _ := time.Parse(time.RFC3339, "2006-01-02T15:00:00Z") err := validator.Validate( context.Background(), validation.NilTime(&t, it.IsEarlierThan(compared)), ) fmt.Println(err) }
Output: violation: This value should be earlier than 2006-01-02T15:00:00Z.
func NilTimeProperty ¶ added in v0.5.0
func NilTimeProperty(name string, value *time.Time, constraints ...TimeConstraint) ValidatorArgument
NilTimeProperty argument is an alias for NilTime that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "time" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { CreatedAt time.Time }{ CreatedAt: time.Now(), } compared, _ := time.Parse(time.RFC3339, "2006-01-02T15:00:00Z") err := validator.Validate( context.Background(), validation.NilTimeProperty("createdAt", &v.CreatedAt, it.IsEarlierThan(compared)), ) fmt.Println(err) }
Output: violation at 'createdAt': This value should be earlier than 2006-01-02T15:00:00Z.
func Number ¶
func Number[T Numeric](value T, constraints ...NumberConstraint[T]) ValidatorArgument
Number argument is used to validate numbers.
Example (Float) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 5.5 err := validator.Validate( context.Background(), validation.Number[float64](v, it.IsGreaterThan(6.5)), ) fmt.Println(err) }
Output: violation: This value should be greater than 6.5.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := 5 err := validator.Validate( context.Background(), validation.Number[int](v, it.IsGreaterThan(5)), ) fmt.Println(err) }
Output: violation: This value should be greater than 5.
func NumberProperty ¶
func NumberProperty[T Numeric](name string, value T, constraints ...NumberConstraint[T]) ValidatorArgument
NumberProperty argument is an alias for Number that automatically adds property name to the current scope.
Example (Float) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Amount float64 }{ Amount: 5.5, } err := validator.Validate( context.Background(), validation.NumberProperty[float64]("amount", v.Amount, it.IsGreaterThan(6.5)), ) fmt.Println(err) }
Output: violation at 'amount': This value should be greater than 6.5.
Example (Int) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { Count int }{ Count: 5, } err := validator.Validate( context.Background(), validation.NumberProperty[int]("count", v.Count, it.IsGreaterThan(5)), ) fmt.Println(err) }
Output: violation at 'count': This value should be greater than 5.
func String ¶
func String(value string, constraints ...StringConstraint) ValidatorArgument
String argument is used to validate strings.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := "" err := validator.Validate( context.Background(), validation.String(v, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: This value should not be blank.
func StringProperty ¶
func StringProperty(name string, value string, constraints ...StringConstraint) ValidatorArgument
StringProperty argument is an alias for String that automatically adds property name to the current scope.
Example ¶
v := Book{Title: ""} err := validator.Validate( context.Background(), validation.StringProperty("title", v.Title, it.IsNotBlank()), ) fmt.Println(err)
Output: violation at 'title': This value should not be blank.
func Time ¶
func Time(value time.Time, constraints ...TimeConstraint) ValidatorArgument
Time argument is used to validate time.Time value.
Example ¶
package main import ( "context" "fmt" "time" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { t := time.Now() compared, _ := time.Parse(time.RFC3339, "2006-01-02T15:00:00Z") err := validator.Validate( context.Background(), validation.Time(t, it.IsEarlierThan(compared)), ) fmt.Println(err) }
Output: violation: This value should be earlier than 2006-01-02T15:00:00Z.
func TimeProperty ¶
func TimeProperty(name string, value time.Time, constraints ...TimeConstraint) ValidatorArgument
TimeProperty argument is an alias for Time that automatically adds property name to the current scope.
Example ¶
package main import ( "context" "fmt" "time" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := struct { CreatedAt time.Time }{ CreatedAt: time.Now(), } compared, _ := time.Parse(time.RFC3339, "2006-01-02T15:00:00Z") err := validator.Validate( context.Background(), validation.TimeProperty("createdAt", v.CreatedAt, it.IsEarlierThan(compared)), ) fmt.Println(err) }
Output: violation at 'createdAt': This value should be earlier than 2006-01-02T15:00:00Z.
func Valid ¶
func Valid(value Validatable) ValidatorArgument
Valid is used to run validation on the Validatable type. This method is recommended to build a complex validation process.
Example (ValidatableSlice) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type Company struct { Name string Address string } type Companies []Company func (companies Companies) Validate(ctx context.Context, validator *validation.Validator) error { violations := validation.ViolationList{} for i, company := range companies { err := validator.AtIndex(i).Validate( ctx, validation.StringProperty("name", company.Name, it.IsNotBlank()), validation.StringProperty("address", company.Address, it.IsNotBlank(), it.HasMinLength(3)), ) // appending violations from err err = violations.AppendFromError(err) // if append returns a non-nil error we should stop validation because an internal error occurred if err != nil { return err } } // we should always convert ViolationList into error by calling the AsError method // otherwise empty violations list will be interpreted as an error return violations.AsError() } func main() { companies := Companies{ {"MuonSoft", "London"}, {"", "x"}, } err := validator.Validate(context.Background(), validation.Valid(companies)) if violations, ok := validation.UnwrapViolationList(err); ok { for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } }
Output: violation at '[1].name': This value should not be blank. violation at '[1].address': This value is too short. It should have 3 characters or more.
Example (ValidatableStruct) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) type Product struct { Name string Tags []string Components []Component } func (p Product) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( ctx, validation.StringProperty("name", p.Name, it.IsNotBlank()), validation.CountableProperty("tags", len(p.Tags), it.HasMinCount(5)), validation.ComparablesProperty[string]("tags", p.Tags, it.HasUniqueValues[string]()), validation.EachStringProperty("tags", p.Tags, it.IsNotBlank()), validation.CountableProperty("components", len(p.Components), it.HasMinCount(1)), // this runs validation on each of the components validation.ValidSliceProperty("components", p.Components), ) } type Component struct { ID int Name string Tags []string } func (c Component) Validate(ctx context.Context, validator *validation.Validator) error { return validator.Validate( ctx, validation.StringProperty("name", c.Name, it.IsNotBlank()), validation.CountableProperty("tags", len(c.Tags), it.HasMinCount(1)), ) } func main() { p := Product{ Name: "", Tags: []string{"device", "", "phone", "device"}, Components: []Component{ { ID: 1, Name: "", }, }, } err := validator.Validate(context.Background(), validation.Valid(p)) if violations, ok := validation.UnwrapViolationList(err); ok { for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } } }
Output: violation at 'name': This value should not be blank. violation at 'tags': This collection should contain 5 elements or more. violation at 'tags': This collection should contain only unique elements. violation at 'tags[1]': This value should not be blank. violation at 'components[0].name': This value should not be blank. violation at 'components[0].tags': This collection should contain 1 element or more.
func ValidMap ¶ added in v0.9.0
func ValidMap[T Validatable](values map[string]T) ValidatorArgument
ValidMap is a generic argument used to run validation on the map of Validatable types. This method is recommended to build a complex validation process.
func ValidMapProperty ¶ added in v0.9.0
func ValidMapProperty[T Validatable](name string, values map[string]T) ValidatorArgument
ValidMapProperty argument is an alias for ValidSlice that automatically adds property name to the current scope.
func ValidProperty ¶
func ValidProperty(name string, value Validatable) ValidatorArgument
ValidProperty argument is an alias for Valid that automatically adds property name to the current scope.
func ValidSlice ¶ added in v0.9.0
func ValidSlice[T Validatable](values []T) ValidatorArgument
ValidSlice is a generic argument used to run validation on the slice of Validatable types. This method is recommended to build a complex validation process.
func ValidSliceProperty ¶ added in v0.9.0
func ValidSliceProperty[T Validatable](name string, values []T) ValidatorArgument
ValidSliceProperty argument is an alias for ValidSlice that automatically adds property name to the current scope.
func (ValidatorArgument) When ¶ added in v0.9.0
func (arg ValidatorArgument) When(condition bool) ValidatorArgument
When enables conditional validation of this argument. If the expression evaluates to false, then the argument will be ignored.
func (ValidatorArgument) With ¶ added in v0.9.0
func (arg ValidatorArgument) With(options ...Option) ValidatorArgument
With returns a copy of ValidatorArgument with appended options.
type ValidatorOption ¶
type ValidatorOption func(options *ValidatorOptions) error
ValidatorOption is a base type for configuration options used to create a new instance of Validator.
func DefaultLanguage ¶
func DefaultLanguage(tag language.Tag) ValidatorOption
DefaultLanguage option is used to set up the default language for translation of violation messages.
func SetTranslator ¶ added in v0.6.0
func SetTranslator(translator Translator) ValidatorOption
SetTranslator option is used to set up the custom implementation of message violation translator.
func SetViolationFactory ¶
func SetViolationFactory(factory ViolationFactory) ValidatorOption
SetViolationFactory option can be used to override the mechanism of violation creation.
func StoredConstraint ¶ added in v0.2.0
func StoredConstraint(key string, constraint interface{}) ValidatorOption
StoredConstraint option can be used to store a constraint in an internal validator store. It can later be used by the validator.ValidateBy method. This can be useful for passing custom or prepared constraints to Validatable.
If the constraint already exists, a ConstraintAlreadyStoredError will be returned.
Example ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" ) func main() { validator, err := validation.NewValidator( validation.StoredConstraint("notEmpty", it.IsNotBlank().Message("value should not be empty")), ) if err != nil { log.Fatal(err) } err = validator.ValidateString( context.Background(), "", validator.GetConstraint("notEmpty").(validation.StringConstraint), ) fmt.Println(err) }
Output: violation: value should not be empty
func Translations ¶
Translations option is used to load translation messages into the validator.
By default, all violation messages are generated in the English language with pluralization capabilities. To use a custom language you have to load translations on validator initialization. Built-in translations are available in the sub-packages of the package "github.com/muonsoft/message/translations". The translation mechanism is provided by the "golang.org/x/text" package (be aware, it has no stable version yet).
Example ¶
package main import ( "context" "fmt" "log" "github.com/muonsoft/language" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/message/translations/russian" ) func main() { validator, err := validation.NewValidator( validation.Translations(russian.Messages), ) if err != nil { log.Fatal(err) } s := "" ctx := language.WithContext(context.Background(), language.Russian) err = validator.Validate( ctx, validation.String(s, it.IsNotBlank()), ) fmt.Println(err) }
Output: violation: Значение не должно быть пустым.
type ValidatorOptions ¶ added in v0.6.0
type ValidatorOptions struct {
// contains filtered or unexported fields
}
ValidatorOptions is a temporary structure for collecting functional options ValidatorOption.
type Violation ¶
type Violation interface { error // Code is unique, short, and semantic string that can be used to programmatically // test for specific violation. All "code" values are defined in the "github.com/muonsoft/validation/code" package // and are protected by backward compatibility rules. Code() string // Is can be used to check that the violation contains one of the specific codes. // For an empty list, it should always returns false. Is(codes ...string) bool // Message is a translated message with injected values from constraint. It can be used to show // a description of a violation to the end-user. Possible values for build-in constraints // are defined in the "github.com/muonsoft/validation/message" package and can be changed at any time, // even in patch versions. Message() string // MessageTemplate is a template for rendering message. Alongside parameters it can be used to // render the message on the client-side of the library. MessageTemplate() string // Parameters is the map of the template variables and their values provided by the specific constraint. Parameters() []TemplateParameter // PropertyPath is a path that points to the violated property. // See PropertyPath type description for more info. PropertyPath() *PropertyPath }
Violation is the abstraction for validator errors. You can use your own implementations on the application side to use it for your needs. In order for the validator to generate application violations, it is necessary to implement the ViolationFactory interface and inject it into the validator. You can do this by using the SetViolationFactory option in the NewValidator constructor.
func UnwrapViolation ¶
UnwrapViolation is a short function to unwrap Violation from the error.
type ViolationBuilder ¶
type ViolationBuilder struct {
// contains filtered or unexported fields
}
ViolationBuilder used to build an instance of a Violation.
func NewViolationBuilder ¶
func NewViolationBuilder(factory ViolationFactory) *ViolationBuilder
NewViolationBuilder creates a new ViolationBuilder.
func (*ViolationBuilder) AddParameter ¶
func (b *ViolationBuilder) AddParameter(name, value string) *ViolationBuilder
AddParameter adds one parameter into a slice of parameters.
func (*ViolationBuilder) BuildViolation ¶
func (b *ViolationBuilder) BuildViolation(code, message string) *ViolationBuilder
BuildViolation creates a new ViolationBuilder for composing Violation object fluently.
func (*ViolationBuilder) CreateViolation ¶
func (b *ViolationBuilder) CreateViolation() Violation
CreateViolation creates a new violation with given parameters and returns it. Violation is created by calling the CreateViolation method of the ViolationFactory.
func (*ViolationBuilder) SetLanguage ¶
func (b *ViolationBuilder) SetLanguage(tag language.Tag) *ViolationBuilder
SetLanguage sets language that will be used to translate the violation message.
func (*ViolationBuilder) SetParameters ¶
func (b *ViolationBuilder) SetParameters(parameters ...TemplateParameter) *ViolationBuilder
SetParameters sets template parameters that can be injected into the violation message.
func (*ViolationBuilder) SetPluralCount ¶
func (b *ViolationBuilder) SetPluralCount(pluralCount int) *ViolationBuilder
SetPluralCount sets a plural number that will be used for message pluralization during translations.
func (*ViolationBuilder) SetPropertyPath ¶
func (b *ViolationBuilder) SetPropertyPath(path *PropertyPath) *ViolationBuilder
SetPropertyPath sets a property path of violated attribute.
type ViolationFactory ¶
type ViolationFactory interface { // CreateViolation creates a new instance of Violation. CreateViolation( code, messageTemplate string, pluralCount int, parameters []TemplateParameter, propertyPath *PropertyPath, lang language.Tag, ) Violation }
ViolationFactory is the abstraction that can be used to create custom violations on the application side. Use the SetViolationFactory option on the NewValidator constructor to inject your own factory into the validator.
type ViolationList ¶
type ViolationList struct {
// contains filtered or unexported fields
}
ViolationList is a linked list of violations. It is the usual type of error that is returned from a validator.
func NewViolationList ¶ added in v0.3.0
func NewViolationList(violations ...Violation) *ViolationList
NewViolationList creates a new ViolationList, that can be immediately populated with variadic arguments of violations.
func UnwrapViolationList ¶
func UnwrapViolationList(err error) (*ViolationList, bool)
UnwrapViolationList is a short function to unwrap ViolationList from the error.
func (*ViolationList) Append ¶ added in v0.3.0
func (list *ViolationList) Append(violations ...Violation)
Append appends violations to the end of the linked list.
func (*ViolationList) AppendFromError ¶
func (list *ViolationList) AppendFromError(err error) error
AppendFromError appends a single violation or a slice of violations into the end of a given slice. If an error does not implement the Violation or ViolationList interface, it will return an error itself. Otherwise nil will be returned.
Example (AddingError) ¶
package main import ( "errors" "fmt" "github.com/muonsoft/validation" ) func main() { violations := validation.NewViolationList() err := errors.New("error") appendErr := violations.AppendFromError(err) fmt.Println("append error:", appendErr) fmt.Println("violations length:", violations.Len()) }
Output: append error: error violations length: 0
Example (AddingViolation) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) func main() { violations := validation.NewViolationList() err := validator.BuildViolation(context.Background(), "", "foo").CreateViolation() appendErr := violations.AppendFromError(err) fmt.Println("append error:", appendErr) fmt.Println("violations:", violations) }
Output: append error: <nil> violations: violation: foo
Example (AddingViolationList) ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) func main() { violations := validation.NewViolationList() err := validation.NewViolationList( validator.BuildViolation(context.Background(), "", "foo").CreateViolation(), validator.BuildViolation(context.Background(), "", "bar").CreateViolation(), ) appendErr := violations.AppendFromError(err) fmt.Println("append error:", appendErr) fmt.Println("violations:", violations) }
Output: append error: <nil> violations: violation: foo; violation: bar
func (*ViolationList) AsError ¶
func (list *ViolationList) AsError() error
AsError converts the list of violations to an error. This method correctly handles cases where the list of violations is empty. It returns nil on an empty list, indicating that the validation was successful.
func (*ViolationList) AsSlice ¶ added in v0.3.0
func (list *ViolationList) AsSlice() []Violation
AsSlice converts underlying linked list into slice of Violation.
func (*ViolationList) Each ¶ added in v0.7.0
func (list *ViolationList) Each(f func(i int, violation Violation) error) error
Each can be used to iterate over ViolationList by a callback function. If callback returns any error, then it will be returned as a result of Each function.
func (*ViolationList) Error ¶
func (list *ViolationList) Error() string
Error returns a formatted list of errors as a string.
func (*ViolationList) Filter ¶
func (list *ViolationList) Filter(codes ...string) *ViolationList
Filter returns a new list of violations with violations of given codes.
func (*ViolationList) First ¶ added in v0.3.0
func (list *ViolationList) First() *ViolationListElement
First returns the first element of the linked list.
Example ¶
package main import ( "context" "fmt" "github.com/muonsoft/validation" "github.com/muonsoft/validation/validator" ) func main() { violations := validation.NewViolationList( validator.BuildViolation(context.Background(), "", "foo").CreateViolation(), validator.BuildViolation(context.Background(), "", "bar").CreateViolation(), ) for violation := violations.First(); violation != nil; violation = violation.Next() { fmt.Println(violation) } }
Output: violation: foo violation: bar
func (*ViolationList) Has ¶
func (list *ViolationList) Has(codes ...string) bool
Has can be used to check that at least one of the violations contains one of the specific codes. For an empty list of codes, it should always returns false.
func (*ViolationList) Join ¶ added in v0.3.0
func (list *ViolationList) Join(violations *ViolationList)
Join is used to append the given violation list to the end of the current list.
func (*ViolationList) Last ¶ added in v0.3.0
func (list *ViolationList) Last() *ViolationListElement
Last returns the last element of the linked list.
func (*ViolationList) Len ¶ added in v0.3.0
func (list *ViolationList) Len() int
Len returns length of the linked list.
func (*ViolationList) MarshalJSON ¶ added in v0.3.0
func (list *ViolationList) MarshalJSON() ([]byte, error)
MarshalJSON marshals the linked list into JSON. Usually, you should use json.Marshal function for marshaling purposes.
type ViolationListElement ¶ added in v0.3.0
type ViolationListElement struct {
// contains filtered or unexported fields
}
ViolationListElement points to violation build by validator. It also implements Violation and can be used as a proxy to underlying violation.
func (*ViolationListElement) Code ¶ added in v0.3.0
func (element *ViolationListElement) Code() string
func (*ViolationListElement) Error ¶ added in v0.3.0
func (element *ViolationListElement) Error() string
func (*ViolationListElement) Is ¶ added in v0.3.0
func (element *ViolationListElement) Is(codes ...string) bool
func (*ViolationListElement) Message ¶ added in v0.3.0
func (element *ViolationListElement) Message() string
func (*ViolationListElement) MessageTemplate ¶ added in v0.3.0
func (element *ViolationListElement) MessageTemplate() string
func (*ViolationListElement) Next ¶ added in v0.3.0
func (element *ViolationListElement) Next() *ViolationListElement
Next returns next element of the linked list.
func (*ViolationListElement) Parameters ¶ added in v0.3.0
func (element *ViolationListElement) Parameters() []TemplateParameter
func (*ViolationListElement) PropertyPath ¶ added in v0.3.0
func (element *ViolationListElement) PropertyPath() *PropertyPath
func (*ViolationListElement) Violation ¶ added in v0.3.0
func (element *ViolationListElement) Violation() Violation
Violation returns underlying violation value.
type WhenArgument ¶ added in v0.9.0
type WhenArgument struct {
// contains filtered or unexported fields
}
WhenArgument is used to build conditional validation. Use the When function to initiate a conditional check. If the condition is true, then the arguments passed through the Then function will be processed. Otherwise, the arguments passed through the Else function will be processed.
func When ¶ added in v0.2.0
func When(isTrue bool) WhenArgument
When function is used to initiate conditional validation. If the condition is true, then the arguments passed through the Then function will be processed. Otherwise, the arguments passed through the Else function will be processed.
Example ¶
package main import ( "context" "fmt" "regexp" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { visaRegex := regexp.MustCompile("^4[0-9]{12}(?:[0-9]{3})?$") masterCardRegex := regexp.MustCompile("^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$") payment := struct { CardType string CardNumber string Amount int }{ CardType: "Visa", CardNumber: "4111", Amount: 1000, } err := validator.Validate( context.Background(), validation.ComparableProperty[string]( "cardType", payment.CardType, it.IsOneOf("Visa", "MasterCard"), ), validation.When(payment.CardType == "Visa"). With(validation.PropertyName("cardNumber")). Then(validation.String(payment.CardNumber, it.Matches(visaRegex))). Else(validation.String(payment.CardNumber, it.Matches(masterCardRegex))), ) fmt.Println(err) }
Output: violation at 'cardNumber': This value is not valid.
func (WhenArgument) Else ¶ added in v0.9.0
func (arg WhenArgument) Else(arguments ...Argument) WhenArgument
Else function is used to set a sequence of arguments to be processed if a condition is false.
Example ¶
package main import ( "context" "fmt" "regexp" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := "123" err := validator.Validate( context.Background(), validation.When(true). Then(validation.String(v, it.Matches(regexp.MustCompile(`^\w+$`)))). Else(validation.String(v, it.Matches(regexp.MustCompile(`^\d+$`)))), ) fmt.Println(err) }
Output: <nil>
func (WhenArgument) Then ¶ added in v0.9.0
func (arg WhenArgument) Then(arguments ...Argument) WhenArgument
Then function is used to set a sequence of arguments to be processed if the condition is true.
Example ¶
package main import ( "context" "fmt" "regexp" "github.com/muonsoft/validation" "github.com/muonsoft/validation/it" "github.com/muonsoft/validation/validator" ) func main() { v := "foo" err := validator.Validate( context.Background(), validation.When(true).Then( validation.String(v, it.Matches(regexp.MustCompile(`^\w+$`))), ), ) fmt.Println(err) }
Output: <nil>
func (WhenArgument) With ¶ added in v0.9.0
func (arg WhenArgument) With(options ...Option) WhenArgument
With returns a copy of WhenArgument with appended options.
type WhenGroupsArgument ¶ added in v0.9.0
type WhenGroupsArgument struct {
// contains filtered or unexported fields
}
WhenGroupsArgument is used to build conditional validation based on groups. Use the WhenGroups function to initiate a conditional check. If validation group matches to the validator one, then the arguments passed through the Then function will be processed. Otherwise, the arguments passed through the Else function will be processed.
func WhenGroups ¶ added in v0.9.0
func WhenGroups(groups ...string) WhenGroupsArgument
WhenGroups is used to build conditional validation based on groups. If validation group matches to the validator one, then the arguments passed through the Then function will be processed. Otherwise, the arguments passed through the Else function will be processed.
func (WhenGroupsArgument) Else ¶ added in v0.9.0
func (arg WhenGroupsArgument) Else(arguments ...Argument) WhenGroupsArgument
Else function is used to set a sequence of arguments to be processed if the validation group is active.
func (WhenGroupsArgument) Then ¶ added in v0.9.0
func (arg WhenGroupsArgument) Then(arguments ...Argument) WhenGroupsArgument
Then function is used to set a sequence of arguments to be processed if the validation group is active.
func (WhenGroupsArgument) With ¶ added in v0.9.0
func (arg WhenGroupsArgument) With(options ...Option) WhenGroupsArgument
With returns a copy of WhenArgument with appended options.
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
Package code contains a list of unique, short, and semantic violation codes.
|
Package code contains a list of unique, short, and semantic violation codes. |
Package is contains standalone functions that can be used for custom validation process.
|
Package is contains standalone functions that can be used for custom validation process. |
Package it contains validation constraints that are used to validate specific types of values.
|
Package it contains validation constraints that are used to validate specific types of values. |
Package message contains violation message templates.
|
Package message contains violation message templates. |
translations/english
Package english contains violation message texts translated into English language.
|
Package english contains violation message texts translated into English language. |
translations/russian
Package russian contains violation message texts translated into Russian language.
|
Package russian contains violation message texts translated into Russian language. |
Package test contains tests for validation
|
Package test contains tests for validation |
Package validate contains standalone functions that can be used for custom validation process.
|
Package validate contains standalone functions that can be used for custom validation process. |
Package validationtest contains helper functions for testing purposes.
|
Package validationtest contains helper functions for testing purposes. |
Package validator contains Validator service singleton.
|
Package validator contains Validator service singleton. |