[Go] Package of validators and sanitizers for strings, numerics, slices and structs

Overview

govalidator

Gitter GoDoc Build Status Coverage Go Report Card GoSearch Backers on Open Collective Sponsors on Open Collective FOSSA Status

A package of validators and sanitizers for strings, structs and collections. Based on validator.js.

Installation

Make sure that Go is installed on your computer. Type the following command in your terminal:

go get github.com/asaskevich/govalidator

or you can get specified release of the package with gopkg.in:

go get gopkg.in/asaskevich/govalidator.v10

After it the package is ready to use.

Import package in your project

Add following line in your *.go file:

import "github.com/asaskevich/govalidator"

If you are unhappy to use long govalidator, you can do something like this:

import (
  valid "github.com/asaskevich/govalidator"
)

Activate behavior to require all fields have a validation tag by default

SetFieldsRequiredByDefault causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using valid:"-" or valid:"email,optional"). A good place to activate this is a package init function or the main() function.

SetNilPtrAllowedByRequired causes validation to pass when struct fields marked by required are set to nil. This is disabled by default for consistency, but some packages that need to be able to determine between nil and zero value state can use this. If disabled, both nil and zero values cause validation errors.

import "github.com/asaskevich/govalidator"

func init() {
  govalidator.SetFieldsRequiredByDefault(true)
}

Here's some code to explain it:

// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
type exampleStruct struct {
  Name  string ``
  Email string `valid:"email"`
}

// this, however, will only fail when Email is empty or an invalid email address:
type exampleStruct2 struct {
  Name  string `valid:"-"`
  Email string `valid:"email"`
}

// lastly, this will only fail when Email is an invalid email address but not when it's empty:
type exampleStruct2 struct {
  Name  string `valid:"-"`
  Email string `valid:"email,optional"`
}

Recent breaking changes (see #123)

Custom validator function signature

A context was added as the second parameter, for structs this is the object being validated – this makes dependent validation possible.

import "github.com/asaskevich/govalidator"

// old signature
func(i interface{}) bool

// new signature
func(i interface{}, o interface{}) bool
Adding a custom validator

This was changed to prevent data races when accessing custom validators.

import "github.com/asaskevich/govalidator"

// before
govalidator.CustomTypeTagMap["customByteArrayValidator"] = func(i interface{}, o interface{}) bool {
  // ...
}

// after
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, o interface{}) bool {
  // ...
})

List of functions:

func Abs(value float64) float64
func BlackList(str, chars string) string
func ByteLength(str string, params ...string) bool
func CamelCaseToUnderscore(str string) string
func Contains(str, substring string) bool
func Count(array []interface{}, iterator ConditionIterator) int
func Each(array []interface{}, iterator Iterator)
func ErrorByField(e error, field string) string
func ErrorsByField(e error) map[string]string
func Filter(array []interface{}, iterator ConditionIterator) []interface{}
func Find(array []interface{}, iterator ConditionIterator) interface{}
func GetLine(s string, index int) (string, error)
func GetLines(s string) []string
func HasLowerCase(str string) bool
func HasUpperCase(str string) bool
func HasWhitespace(str string) bool
func HasWhitespaceOnly(str string) bool
func InRange(value interface{}, left interface{}, right interface{}) bool
func InRangeFloat32(value, left, right float32) bool
func InRangeFloat64(value, left, right float64) bool
func InRangeInt(value, left, right interface{}) bool
func IsASCII(str string) bool
func IsAlpha(str string) bool
func IsAlphanumeric(str string) bool
func IsBase64(str string) bool
func IsByteLength(str string, min, max int) bool
func IsCIDR(str string) bool
func IsCRC32(str string) bool
func IsCRC32b(str string) bool
func IsCreditCard(str string) bool
func IsDNSName(str string) bool
func IsDataURI(str string) bool
func IsDialString(str string) bool
func IsDivisibleBy(str, num string) bool
func IsEmail(str string) bool
func IsExistingEmail(email string) bool
func IsFilePath(str string) (bool, int)
func IsFloat(str string) bool
func IsFullWidth(str string) bool
func IsHalfWidth(str string) bool
func IsHash(str string, algorithm string) bool
func IsHexadecimal(str string) bool
func IsHexcolor(str string) bool
func IsHost(str string) bool
func IsIP(str string) bool
func IsIPv4(str string) bool
func IsIPv6(str string) bool
func IsISBN(str string, version int) bool
func IsISBN10(str string) bool
func IsISBN13(str string) bool
func IsISO3166Alpha2(str string) bool
func IsISO3166Alpha3(str string) bool
func IsISO4217(str string) bool
func IsISO693Alpha2(str string) bool
func IsISO693Alpha3b(str string) bool
func IsIn(str string, params ...string) bool
func IsInRaw(str string, params ...string) bool
func IsInt(str string) bool
func IsJSON(str string) bool
func IsLatitude(str string) bool
func IsLongitude(str string) bool
func IsLowerCase(str string) bool
func IsMAC(str string) bool
func IsMD4(str string) bool
func IsMD5(str string) bool
func IsMagnetURI(str string) bool
func IsMongoID(str string) bool
func IsMultibyte(str string) bool
func IsNatural(value float64) bool
func IsNegative(value float64) bool
func IsNonNegative(value float64) bool
func IsNonPositive(value float64) bool
func IsNotNull(str string) bool
func IsNull(str string) bool
func IsNumeric(str string) bool
func IsPort(str string) bool
func IsPositive(value float64) bool
func IsPrintableASCII(str string) bool
func IsRFC3339(str string) bool
func IsRFC3339WithoutZone(str string) bool
func IsRGBcolor(str string) bool
func IsRequestURI(rawurl string) bool
func IsRequestURL(rawurl string) bool
func IsRipeMD128(str string) bool
func IsRipeMD160(str string) bool
func IsRsaPub(str string, params ...string) bool
func IsRsaPublicKey(str string, keylen int) bool
func IsSHA1(str string) bool
func IsSHA256(str string) bool
func IsSHA384(str string) bool
func IsSHA512(str string) bool
func IsSSN(str string) bool
func IsSemver(str string) bool
func IsTiger128(str string) bool
func IsTiger160(str string) bool
func IsTiger192(str string) bool
func IsTime(str string, format string) bool
func IsType(v interface{}, params ...string) bool
func IsURL(str string) bool
func IsUTFDigit(str string) bool
func IsUTFLetter(str string) bool
func IsUTFLetterNumeric(str string) bool
func IsUTFNumeric(str string) bool
func IsUUID(str string) bool
func IsUUIDv3(str string) bool
func IsUUIDv4(str string) bool
func IsUUIDv5(str string) bool
func IsUnixTime(str string) bool
func IsUpperCase(str string) bool
func IsVariableWidth(str string) bool
func IsWhole(value float64) bool
func LeftTrim(str, chars string) string
func Map(array []interface{}, iterator ResultIterator) []interface{}
func Matches(str, pattern string) bool
func MaxStringLength(str string, params ...string) bool
func MinStringLength(str string, params ...string) bool
func NormalizeEmail(str string) (string, error)
func PadBoth(str string, padStr string, padLen int) string
func PadLeft(str string, padStr string, padLen int) string
func PadRight(str string, padStr string, padLen int) string
func PrependPathToErrors(err error, path string) error
func Range(str string, params ...string) bool
func RemoveTags(s string) string
func ReplacePattern(str, pattern, replace string) string
func Reverse(s string) string
func RightTrim(str, chars string) string
func RuneLength(str string, params ...string) bool
func SafeFileName(str string) string
func SetFieldsRequiredByDefault(value bool)
func SetNilPtrAllowedByRequired(value bool)
func Sign(value float64) float64
func StringLength(str string, params ...string) bool
func StringMatches(s string, params ...string) bool
func StripLow(str string, keepNewLines bool) string
func ToBoolean(str string) (bool, error)
func ToFloat(str string) (float64, error)
func ToInt(value interface{}) (res int64, err error)
func ToJSON(obj interface{}) (string, error)
func ToString(obj interface{}) string
func Trim(str, chars string) string
func Truncate(str string, length int, ending string) string
func TruncatingErrorf(str string, args ...interface{}) error
func UnderscoreToCamelCase(s string) string
func ValidateMap(inputMap map[string]interface{}, validationMap map[string]interface{}) (bool, error)
func ValidateStruct(s interface{}) (bool, error)
func WhiteList(str, chars string) string
type ConditionIterator
type CustomTypeValidator
type Error
func (e Error) Error() string
type Errors
func (es Errors) Error() string
func (es Errors) Errors() []error
type ISO3166Entry
type ISO693Entry
type InterfaceParamValidator
type Iterator
type ParamValidator
type ResultIterator
type UnsupportedTypeError
func (e *UnsupportedTypeError) Error() string
type Validator

Examples

IsURL
println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
IsType
println(govalidator.IsType("Bob", "string"))
println(govalidator.IsType(1, "int"))
i := 1
println(govalidator.IsType(&i, "*int"))

IsType can be used through the tag type which is essential for map validation:

type User	struct {
  Name string      `valid:"type(string)"`
  Age  int         `valid:"type(int)"`
  Meta interface{} `valid:"type(string)"`
}
result, err := govalidator.ValidateStruct(User{"Bob", 20, "meta"})
if err != nil {
	println("error: " + err.Error())
}
println(result)
ToString
type User struct {
	FirstName string
	LastName string
}

str := govalidator.ToString(&User{"John", "Juan"})
println(str)
Each, Map, Filter, Count for slices

Each iterates over the slice/array and calls Iterator for every item

data := []interface{}{1, 2, 3, 4, 5}
var fn govalidator.Iterator = func(value interface{}, index int) {
	println(value.(int))
}
govalidator.Each(data, fn)
data := []interface{}{1, 2, 3, 4, 5}
var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
	return value.(int) * 3
}
_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
	return value.(int)%2 == 0
}
_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
_ = govalidator.Count(data, fn) // result = 5
ValidateStruct #2

If you want to validate structs, you can use tag valid for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place - in your tag. If you need a validator that is not on the list below, you can add it like this:

govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
	return str == "duck"
})

For completely custom validators (interface-based), see below.

Here is a list of available validators for struct fields (validator - used function):

"email":              IsEmail,
"url":                IsURL,
"dialstring":         IsDialString,
"requrl":             IsRequestURL,
"requri":             IsRequestURI,
"alpha":              IsAlpha,
"utfletter":          IsUTFLetter,
"alphanum":           IsAlphanumeric,
"utfletternum":       IsUTFLetterNumeric,
"numeric":            IsNumeric,
"utfnumeric":         IsUTFNumeric,
"utfdigit":           IsUTFDigit,
"hexadecimal":        IsHexadecimal,
"hexcolor":           IsHexcolor,
"rgbcolor":           IsRGBcolor,
"lowercase":          IsLowerCase,
"uppercase":          IsUpperCase,
"int":                IsInt,
"float":              IsFloat,
"null":               IsNull,
"uuid":               IsUUID,
"uuidv3":             IsUUIDv3,
"uuidv4":             IsUUIDv4,
"uuidv5":             IsUUIDv5,
"creditcard":         IsCreditCard,
"isbn10":             IsISBN10,
"isbn13":             IsISBN13,
"json":               IsJSON,
"multibyte":          IsMultibyte,
"ascii":              IsASCII,
"printableascii":     IsPrintableASCII,
"fullwidth":          IsFullWidth,
"halfwidth":          IsHalfWidth,
"variablewidth":      IsVariableWidth,
"base64":             IsBase64,
"datauri":            IsDataURI,
"ip":                 IsIP,
"port":               IsPort,
"ipv4":               IsIPv4,
"ipv6":               IsIPv6,
"dns":                IsDNSName,
"host":               IsHost,
"mac":                IsMAC,
"latitude":           IsLatitude,
"longitude":          IsLongitude,
"ssn":                IsSSN,
"semver":             IsSemver,
"rfc3339":            IsRFC3339,
"rfc3339WithoutZone": IsRFC3339WithoutZone,
"ISO3166Alpha2":      IsISO3166Alpha2,
"ISO3166Alpha3":      IsISO3166Alpha3,

Validators with parameters

"range(min|max)": Range,
"length(min|max)": ByteLength,
"runelength(min|max)": RuneLength,
"stringlength(min|max)": StringLength,
"matches(pattern)": StringMatches,
"in(string1|string2|...|stringN)": IsIn,
"rsapub(keylength)" : IsRsaPub,
"minstringlength(int): MinStringLength,
"maxstringlength(int): MaxStringLength,

Validators with parameters for any type

"type(type)": IsType,

And here is small example of usage:

type Post struct {
	Title    string `valid:"alphanum,required"`
	Message  string `valid:"duck,ascii"`
	Message2 string `valid:"animal(dog)"`
	AuthorIP string `valid:"ipv4"`
	Date     string `valid:"-"`
}
post := &Post{
	Title:   "My Example Post",
	Message: "duck",
	Message2: "dog",
	AuthorIP: "123.234.54.3",
}

// Add your own struct validation tags
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
	return str == "duck"
})

// Add your own struct validation tags with parameter
govalidator.ParamTagMap["animal"] = govalidator.ParamValidator(func(str string, params ...string) bool {
    species := params[0]
    return str == species
})
govalidator.ParamTagRegexMap["animal"] = regexp.MustCompile("^animal\\((\\w+)\\)$")

result, err := govalidator.ValidateStruct(post)
if err != nil {
	println("error: " + err.Error())
}
println(result)
ValidateMap #2

If you want to validate maps, you can use the map to be validated and a validation map that contain the same tags used in ValidateStruct, both maps have to be in the form map[string]interface{}

So here is small example of usage:

var mapTemplate = map[string]interface{}{
	"name":"required,alpha",
	"family":"required,alpha",
	"email":"required,email",
	"cell-phone":"numeric",
	"address":map[string]interface{}{
		"line1":"required,alphanum",
		"line2":"alphanum",
		"postal-code":"numeric",
	},
}

var inputMap = map[string]interface{}{
	"name":"Bob",
	"family":"Smith",
	"email":"[email protected]",
	"address":map[string]interface{}{
		"line1":"",
		"line2":"",
		"postal-code":"",
	},
}

result, err := govalidator.ValidateMap(inputMap, mapTemplate)
if err != nil {
	println("error: " + err.Error())
}
println(result)
WhiteList
// Remove all characters from string ignoring characters between "a" and "z"
println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
Custom validation functions

Custom validation using your own domain specific validators is also available - here's an example of how to use it:

import "github.com/asaskevich/govalidator"

type CustomByteArray [6]byte // custom types are supported and can be validated

type StructWithCustomByteArray struct {
  ID              CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence
  Email           string          `valid:"email"`
  CustomMinLength int             `valid:"-"`
}

govalidator.CustomTypeTagMap.Set("customByteArrayValidator", func(i interface{}, context interface{}) bool {
  switch v := context.(type) { // you can type switch on the context interface being validated
  case StructWithCustomByteArray:
    // you can check and validate against some other field in the context,
    // return early or not validate against the context at all – your choice
  case SomeOtherType:
    // ...
  default:
    // expecting some other type? Throw/panic here or continue
  }

  switch v := i.(type) { // type switch on the struct field being validated
  case CustomByteArray:
    for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes
      if e != 0 {
        return true
      }
    }
  }
  return false
})
govalidator.CustomTypeTagMap.Set("customMinLengthValidator", func(i interface{}, context interface{}) bool {
  switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation
  case StructWithCustomByteArray:
    return len(v.ID) >= v.CustomMinLength
  }
  return false
})
Loop over Error()

By default .Error() returns all errors in a single String. To access each error you can do this:

  if err != nil {
    errs := err.(govalidator.Errors).Errors()
    for _, e := range errs {
      fmt.Println(e.Error())
    }
  }
Custom error messages

Custom error messages are supported via annotations by adding the ~ separator - here's an example of how to use it:

type Ticket struct {
  Id        int64     `json:"id"`
  FirstName string    `json:"firstname" valid:"required~First name is blank"`
}

Notes

Documentation is available here: godoc.org. Full information about code coverage is also available here: govalidator on gocover.io.

Support

If you do have a contribution to the package, feel free to create a Pull Request or an Issue.

What to contribute

If you don't know what to do, there are some features and functions that need to be done

  • Refactor code
  • Edit docs and README: spellcheck, grammar and typo check
  • Create actual list of contributors and projects that currently using this package
  • Resolve issues and bugs
  • Update actual list of functions
  • Update list of validators that available for ValidateStruct and add new
  • Implement new validators: IsFQDN, IsIMEI, IsPostalCode, IsISIN, IsISRC etc
  • Implement validation by maps
  • Implement fuzzing testing
  • Implement some struct/map/array utilities
  • Implement map/array validation
  • Implement benchmarking
  • Implement batch of examples
  • Look at forks for new features and fixes

Advice

Feel free to create what you want, but keep in mind when you implement new features:

  • Code must be clear and readable, names of variables/constants clearly describes what they are doing
  • Public functions must be documented and described in source file and added to README.md to the list of available functions
  • There are must be unit-tests for any new functions and improvements

Credits

Contributors

This project exists thanks to all the people who contribute. [Contribute].

Special thanks to contributors

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

FOSSA Status

Comments
  • lessEqual(value), moreEqual(value), equal(value), notEqual(value) Options on structs

    lessEqual(value), moreEqual(value), equal(value), notEqual(value) Options on structs

    Currently there are validator functions like IsInt, but sometime it could be even more helpful to restrict the values further with a min or/and a max value. I'd really like to extend.the functionality so that such checks could be done.

    But as of now, I'm not that sure which approach would be the best, therefor I'd like to hear everyones opinion first. I'm open for other ideas or other approaches! This "issue" should be about how to solves this "feature request" the best!

    As my idea goes I would like to introduce 4 new options: lessequal(value), moreequal(value), equal(value), notequal(value). I chose those options as every "validator" is in conjunction with each other. Therefor we can't say less(value) and equal(value) to get lessequal(value), because if "a < b" is true "a = b" can't be true, therefore the validation would always return false.

    the usage would then look like this

    type Foobar struct {
        number1 string `valid:"int,lessequal(5),moreequal(-10),notequal(0)"` //means -10 <= number1 <= 5 && number1 != 0
        cons6 string `valid:"int,equal(6)"` //means cons6 == 6
        number2 string `valid:"int,lessequal(5),notequal(5)"` //means number2 < 5
        name string `valid:"ascii,noequal(admin)"` //means every (ascii) name beside 'admin' is valid
        uuid string `valid:"uuid, moreequal(A0000000-0000-0000-0000-000000000000)"`
    }
    

    we could even add some more options like range(min,max), but at first I'd like to concentrate on the 4 options I mentioned. If this 4 are done right, adding more should be quite easy (especially options like range(min,max))

    Now about how my current approach would look like respectively how I would implement this:

    First of all I would define a basic Validator struct which would be more or less the foundation of most (maybe all) validators.

    //Basic Validator
    type basicValidatorType struct {
        less  func(v1, v2 interface{}) bool
        more  func(v1, v2 interface{}) bool
        equal func(v1, v2 interface{}) bool
    }
    
    func (b basicValidatorType) isLessEqual(value, referenceValue string) bool {
        v, errV := b.convert(value)
        r, errR := b.convert(referenceValue)
        if errV != nil || errR != nil {
            return false
        }
        if b.equal != nil && b.equal(v, r) {
            return true
        }
        if b.equal == nil && reflect.DeepEqual(v, r) {
            return true
        }
        if b.less != nil && b.less(v, r) {
            return true
        }
        return false
    }
    func (b basicValidatorType) isMoreEqual(value, referenceValue string) bool {
        v, errV := b.convert(value)
        r, errR := b.convert(referenceValue)
        if errV != nil || errR != nil {
            return false
        }
        if b.equal != nil && b.equal(v, r) {
            return true
        }
        if b.equal == nil && reflect.DeepEqual(v, r) {
            return true
        }
        if b.more != nil && b.more(v, r) {
            return true
        }
        return false
    }
    func (b basicValidatorType) isEqual(value, referenceValue string) bool {
        v, errV := b.convert(value)
        r, errR := b.convert(referenceValue)
        if errV != nil || errR != nil {
            return false
        }
        if b.equal == nil {
            return reflect.DeepEqual(v, r)
        }
        return b.equal(v, r)
    }
    func (b basicValidatorType) isNotEqual(value, referenceValue string) bool {
        v, errV := b.convert(value)
        r, errR := b.convert(referenceValue)
        if errV != nil || errR != nil {
            return false
        }
        if b.equal == nil {
            return !reflect.DeepEqual(v, r)
        }
        return !b.equal(v, r)
    }
    func (b basicValidatorType) convert(value string) (interface{}, error) {
        return value, nil
    }
    

    The validators then would look like this (here an example of how IsInt would look like)

    //ValidatorType for IsInt
    type validatorInt basicValidatorType
    
    func (v validatorInt) convert(value string) (interface{}, error) {
        valueInt, err := strconv.ParseInt(value, 10, 64)
        return valueInt, err
    }
    
    var intValidator = validatorInt{
        //less
        func(v1, v2 interface{}) bool {
            int1, ok1 := v1.(int64)
            int2, ok2 := v2.(int64)
            if ok1 != true || ok2 != true {
                return false
            }
            return int1 < int2
        },
        //more
        func(v1, v2 interface{}) bool {
            int1, ok1 := v1.(int64)
            int2, ok2 := v2.(int64)
            if ok1 != true || ok2 != true {
                return false
            }
            return int1 > int2
        },
        //equal
        func(v1, v2 interface{}) bool {
            int1, ok1 := v1.(int64)
            int2, ok2 := v2.(int64)
            if ok1 != true || ok2 != true {
                return false
            }
            return int1 == int2
        },
    }
    
    func IsInt(str string) bool {
        _, err := intValidator.convert(str)
        return err == nil
    }
    

    To do all this I would need (IMO) to rebuild the whole validation process as shown in my example of IsInt. Rebuilden the whole code is something I'd like to avoid, therefor the questions are, if anyone has a better solution/approach or some ideas how to reduce code or the need to change code with my idea?

    Things I currently don't like on my idea but haven't found better solutions:

    1. To much heap allocations (e.g var intValidator)
    opened by Dadie 16
  • Validate empty values

    Validate empty values

    Currently govalidator skips validation of zero numbers, empty strings, and other zero values of any type. It treats them as always valid. On the other hand, govalidator errs when a 'required' field has a zero value which disallows entering zero values into required fields.

    The goal of this PR is to solve both problems: to validate zero values and to allow 'required' fields to have zero/empty values.

    The main idea is to skip validation only when we are sure that a value is a nil-value (we can distinguish nil values from zero/empty values only for pointers, interfaces, maps, and slices; we consider all other values as non-nil values). All non-nil values are being validated. The 'required` validator errs only for nil values.

    If one wants to check that some required string or number is given, he/she can declare them as pointers:

    type MyStruct struct {
       Name     *string `valid:"required"`
       Number *int       `valid:"required"`
    }
    

    This will fail when Name and/or Number are not given or equal to nil.

    When one wants to disallow empty strings, it's still possible to use the runelength validator. And there is also the range validator for numeric values.

    This PR fixes #276, #274, (probably) #260, #256, #246, (probably) #149, (probably) #136, #130.

    opened by zenovich 10
  • Validating struct inside struct where the kind of nested struct field is a pointer

    Validating struct inside struct where the kind of nested struct field is a pointer

    If the nested struct kind is a pointer/slice, it is not caught at validator.go:580

    		if valueField.Kind() == reflect.Struct {
    			var err error
    			structResult, err = ValidateStruct(valueField.Interface())
    			if err != nil {
    				errs = append(errs, err)
    			}
    		}
    

    Is that intentionally left out? If not, it would be awesome if that feature could be added.

    opened by arnavsharma93 9
  • how to return message with multile languages ?

    how to return message with multile languages ?

    the scenes is that I hav many languages that will return for validate failed . such as :

    
    type exampleStruct struct {
      Name  string ``
      Email string `valid:"email"`  //    email is not correct || email 格式错误 
    }
    
    

    how can I defined it .

    opened by clearcodecn 8
  • How to validated boolean value?

    How to validated boolean value?

    type Request struct { Active bool json:"active" valid:"required~Status should not be blank" }

    When active variable have value "false" its always invalidate.

    opened by shivkumarsingh7 8
  • Fix validator processing errors

    Fix validator processing errors

    The following bugs have been fixed:

    • ValidateStruct() didn't return an error if an invalid validator was specified in the struct validation tags.
    • Built-in validators weren't processed when a custom validator was specified.

    This commit adds a check which ensures that the value is checked against all specified validators before return that the value is valid.


    This change is Reviewable

    opened by KonishchevDmitry 8
  • IsUTFDigit accepting some Strings it (IMO) shouldn't

    IsUTFDigit accepting some Strings it (IMO) shouldn't

    The IsUTFDigit accepts strings which contains non valid Digit character or aren't even valid numbers.

    IsUTFDigit accepts: "-1" "1-1" "-" "--------1" "1---" IsUTFDigits rejects: "+1" "1+1" "+" "+++++++1" "1+++"

    The question here is, what is the intended reaction of the IsUTFDigit function.

    opened by Dadie 8
  • (Enhancement) Validator: Adding more concrete base64 validation, Enabling []int validation

    (Enhancement) Validator: Adding more concrete base64 validation, Enabling []int validation

    The current base64 validator makes a few assumptions about the nature of the base 64 string as a result of using regex. By using Go's build in base64 lib we circumvent the regex as well as adding full functionally to validate both standard base64 strings and raw base64 strings. This is an additive string, which allows for full backwards capabilities.

    (Enhancement) Validator: Validating contents of []int … Adding a new type to enable the ability to validate what's inside of an int slice. This is important for structured API documentation, when the items in the slice should be known integers. I didn't implement the other slice types as I don't have a use case for them, but it should be easy enough to extend. This is not a breaking change.

    opened by marcsantiago 7
  • _ in URL makes them invalid

    _ in URL makes them invalid

    See https://github.com/prometheus/prometheus/issues/2717

    From that issue: RFC 952 says that:

    1. A "name" (Net, Host, Gateway, or Domain name) is a text string up
       to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus
       sign (-), and period (.)
    

    But the rule apparently isn't strictly followed by DNS servers and names in an /etc/hosts file can contain underscores.

    Do you have any plans to support _?

    bug 
    opened by gouthamve 7
  • Interplay between custom validators and optional fields

    Interplay between custom validators and optional fields

    As far as I understand and can surmise from the code, optional,required annotations are ignored when custom validators are defined on the same field.

    For instance, if I have defined a custom validator called version which allows for regex XX.XX.XXX on this field

        Version  string `json:"version" valid:"optional,version"`
    

    I expect when I am validating my struct as

        _, err = govalidator.ValidateStruct(<struct>)
    

    empty string will be allowed, but it is not!

    I wonder why the design decision was made this way?

    It is most inconvenient and requires users to always handle the empty field case explicitly. It is confusing that the validator which is a part of a standard library

        Email  string `json:"email" valid:"optional,email"`
    

    will work correctly with empty string, but a custom validator

        Version  string `json:"version" valid:"optional,version"`
    

    does not!

    opened by baleksan 6
  • Change struct validator's separator between validators from

    Change struct validator's separator between validators from "," to "\n"

    Hi,

    This change started with the issue that trying to use struct validation using valid:matches(^.{3,}$),required to match any string with at least three characters, the problem is that it includes a comma in the expression.

    In this case, the tagParser() breaks this down as:

    • matches(^.{3
    • }$)
    • required

    Furthermore, since the first two expressions are not recognized, they are ignored silently, and you have to be careful your validations are not being ignored.

    The solution proposed is to change the "," as separator and turn the above struct validation valid:matches(^{.3,}$)\nrequired; The \n character is seldom used in regular expressions matching a single line wo it looks like a better choice, although not standard. The other option is to write a parser that takes this issue into account but would take more time I don't really have at this time.

    Please comment on what you guys think.

    Great piece of code, by the way!

    Regards,

    GM


    This change is Reviewable

    opened by rhaseven7h 6
  • Added IsE164 validation for struct fields

    Added IsE164 validation for struct fields

    | Q | A |---------------- | ------ | Documentation | no | Bugfix | no | BC Break | no | New Feature | yes | RFC | no | QA | no

    Description

    Added IsE164 validation for struct fields

    opened by pskiadas 0
  • add IsPrivateIP

    add IsPrivateIP

    | Q | A |-------------- | ------ | Documentation | yes | Bugfix | no | BC Break | no | New Feature | yes | RFC | yes | QA | yes

    Description

    add IsPrivateIP test ip is private ip

    opened by hktalent 0
  • Is this project abandoned? Is there an active fork of this repo?

    Is this project abandoned? Is there an active fork of this repo?

    This is the second highest starred validation package in Go, but it appears there is no maintainer or activity on this repo.

    I would use go-playground/validator (the highest starred validation package I could find), however it's not suitable for my use-case as I cannot define custom errors per field, whereas asaskevich/govalidator does support this.

    Is there an active fork of this repo?

    opened by OscarVanL 1
  • Do not put any limit on maximum URL length

    Do not put any limit on maximum URL length

    Limitation : Current implementation of IsURL function simply returns false (URL as invalid) if length of URL is more than 2082 runes/characters. It does not check if the URL is valid based on regex and URL-parsing.

    Approach Remove the if-check present on maximum length and allow the function to check if the URL is valid based on regex and URL-parsing.

    opened by ashishshinde-pubm 0
  • IsRequestURI fails for non-absolute URLs

    IsRequestURI fails for non-absolute URLs

    Bug Report

    | Q | A |------------ | ------ | Version(s) | v11.0.1 and earlier?

    Summary

    APIs that return relative URIs fail to validate as url.ParseRequestURI is used instead of url.Parse. ParseRequestURI is documented as:

    ... the url is interpreted only as an absolute URI or an absolute path.

    Current behavior

    Relative URIs fail validation (e.g. ./some-path)

    How to reproduce

    Attempt to validate a relative URI. (e.g. ./some-path)

    Expected behavior

    Aboslute and relative URIs pass validation.

    opened by andrewpmartinez 0
Releases(v11.0.1)
  • v10(Jan 8, 2020)

    • Merge pull request #311 from jackwilsdon/go-fmt-ci Alex Saskevich* 1/8/20, 11:00 PM
    • Merge pull request #299 from okisetiawan0101/new-string-length-tag Alex Saskevich* 1/8/20, 10:59 PM
    • Merge pull request #324 from nathj07/issue320_remove_errant_println Alex Saskevich* 1/8/20, 10:58 PM
    • Merge branch 'master' into issue320_remove_errant_println Alex Saskevich* 1/8/20, 10:57 PM
    • Merge branch 'validatemap' of git://github.com/mie00/govalidator into mie00-validatemap Alex Saskevich 1/8/20, 10:54 PM
    • Merge branch 'mie00-validatemap' Alex Saskevich 1/8/20, 10:51 PM
    • Merge branch 'validatemap' of git://github.com/mie00/govalidator into mie00-validatemap Alex Saskevich 1/8/20, 10:51 PM
    • Merge branch 'France-ioi-do_not_valide_structs_twice_pr' Alex Saskevich 1/8/20, 10:41 PM
    • Merge branch 'do_not_valide_structs_twice_pr' of git://github.com/France-ioi/govalidator into France-ioi-do_not_valide_structs_twice_pr Alex Saskevich 1/8/20, 10:41 PM
    • Merge branch 'France-ioi-fix_TestIsExistingEmail_pr' Alex Saskevich 1/8/20, 10:37 PM
    • Merge branch 'fix_TestIsExistingEmail_pr' of git://github.com/France-ioi/govalidator into France-ioi-fix_TestIsExistingEmail_pr Alex Saskevich 1/8/20, 10:37 PM
    • Merge branch 'master' of https://github.com/asaskevich/govalidator Alex Saskevich 1/8/20, 10:26 PM
    • Merge branch 'France-ioi-required_and_empty_pr' Alex Saskevich 1/8/20, 10:26 PM
    • Merge branch 'required_and_empty_pr' of git://github.com/France-ioi/govalidator into France-ioi-required_and_empty_pr Alex Saskevich 1/8/20, 10:25 PM
    • Merge pull request #319 from bosenok/master Alex Saskevich* 1/8/20, 10:25 PM
    • Merge branch 'dougparrish-fix-345' Alex Saskevich 1/8/20, 10:23 PM
    • Merge branch 'fix-345' of git://github.com/dougparrish/govalidator into dougparrish-fix-345 Alex Saskevich 1/8/20, 10:23 PM
    • Merge branch 'master' of https://github.com/asaskevich/govalidator Alex Saskevich 1/8/20, 10:15 PM
    • Merge branch 'lfaoro-test-iscreditcard' Alex Saskevich 1/8/20, 10:15 PM
    • Updated credit card regexp and added some test cases Alex Saskevich 1/8/20, 10:14 PM
    • Merge pull request #350 from JureMalovrh/fix-utils-typos Alex Saskevich* 1/8/20, 10:13 PM
    • Merge branch 'test-iscreditcard' of git://github.com/lfaoro/govalidator into lfaoro-test-iscreditcard Alex Saskevich 1/8/20, 9:41 PM
    • Fix travis CI script Alex Saskevich 1/8/20, 9:01 PM
    • Merge branch 'master' of https://github.com/asaskevich/govalidator Alex Saskevich 1/8/20, 8:45 PM
    • Merge pull request #347 from cassiosantos/master Alex Saskevich* 1/8/20, 8:43 PM
    • add failing checks on major card brands Leonardo 11/17/19, 4:07 PM
    • improve TestIsCreditCard Leonardo 11/17/19, 3:58 PM
    • Fix typos in utils.go Jure Malovrh 10/2/19, 8:55 PM
    • Fixes #345 - Add accommodation for IPv4 240/8-255/8 to URLIP regexp in patterns.go Doug Parrish 8/22/19, 10:23 PM
    • Fix contributors links Cassio Santos 8/26/19, 4:08 PM
    • go fmt Alex Saskevich 6/15/19, 3:28 PM
    • Add aliases for hashes Alex Saskevich 6/15/19, 3:26 PM
    • Add IsMagnetURI validator Alex Saskevich 6/15/19, 2:50 PM
    • Fix invalid regexps, reduce email regexp, add doc.go Alex Saskevich 6/15/19, 2:07 PM
    • Fix ignored files Alex Saskevich 6/14/19, 12:06 AM
    • validator_test: add test cases for missing validator in ValidateMap Mohamed Elawadi 5/10/19, 4:06 PM
    • validator: ValidateMap: make sure that required fields exist Mohamed Elawadi 5/10/19, 3:02 PM
    • README: add documentation for IsType Mohamed Elawadi 5/10/19, 2:05 PM
    • validator_test: add test cases for IsType Mohamed Elawadi 5/10/19, 1:46 PM
    • validator: add IsType Mohamed Elawadi 5/10/19, 1:43 PM
    • update README for ValidateMap Mohamed Elawadi 5/10/19, 12:50 PM
    • validator_test: add test cases for ValidateMap Mohamed Elawadi 5/10/19, 12:50 PM
    • validator: implement ValidateMap Mohamed Elawadi 5/10/19, 12:49 PM
    • Merge pull request #298 from okisetiawan0101/complete-read-me Alex Saskevich* 4/24/19, 2:10 PM
    • do not validate fields of struct type twice (validate each struct only once) Dmitry Zenovich 3/4/19, 1:09 PM
    • fix TestIsExistingEmail(): bar.coffee -> driftaway.coffee Dmitry Zenovich 3/1/19, 6:41 PM
    • go fmt Dmitry Zenovich 3/1/19, 6:42 PM
    • Do not treat empty strings, zero numbers and structures as nils: validate them, realize that required field can be zeros Dmitry Zenovich 3/1/19, 6:40 PM
    • update tests Nathan Davies 2/24/19, 3:20 PM
    • remove the fmt.Println Nathan Davies 2/24/19, 3:13 PM
    • add Unix Timestamp validator to readme bosenok 12/30/18, 3:53 PM
    • added Unix Timestamp validator bosenok 12/30/18, 3:50 PM
    • Add go fmt as a CI step Jack Wilsdon 10/2/18, 2:53 PM
    • rename isInRaw func to IsInRaw func okisetiawan 7/27/18, 7:41 PM
    • add max string length validator and min string length validator okisetiawan 7/27/18, 7:39 PM
    • add custom tag with params in read me okisetiawan 7/27/18, 7:13 PM
    • Complete the documentation about Validator with parameters in read.me okisetiawan 7/27/18, 6:57 PM
    • Merge pull request #296 from asaskevich/revert-286-master Alex Saskevich* 7/20/18, 2:50 PM
    • Revert "(Enhancement) Validator: Adding more concrete base64 validation, Enabling []int validation " Alex Saskevich* 7/20/18, 2:49 PM
    • Create config.yml Alex Saskevich* 7/20/18, 2:16 PM
    • Merge pull request #286 from marcsantiago/master Alex Saskevich* 7/20/18, 2:12 PM
    • Merge pull request #268 from jasonlam604/feature/Fix_capital_lower_struct_field Alex Saskevich* 7/20/18, 2:07 PM
    • Merge pull request #290 from skybet/feature/include-path-for-nested-structs Alex Saskevich* 7/20/18, 2:05 PM
    • Merge branch 'master' into feature/include-path-for-nested-structs Alex Saskevich* 7/20/18, 2:05 PM
    • Merge pull request #293 from beornf/child-struct-interface Alex Saskevich* 7/20/18, 2:03 PM
    • Merge pull request #270 from es1o/bug_269 Alex Saskevich* 7/20/18, 2:03 PM
    • Merge branch 'master' into bug_269 Alex Saskevich* 7/20/18, 2:03 PM
    • Merge pull request #272 from jasonlam604/feature/add_hasWhitespace_and_hasWhitespaceOnly Alex Saskevich* 7/20/18, 2:01 PM
    • Merge pull request #277 from fossabot/master Alex Saskevich* 7/20/18, 2:00 PM
    • Merge pull request #282 from ferhatelmas/simplification Alex Saskevich* 7/20/18, 1:56 PM
    • Check inner pointer to struct for interface field Beorn Facchini 7/18/18, 12:47 PM
    • Validate the child struct when its an interface Beorn Facchini 7/18/18, 12:06 PM
    • Including the path in errors for nested structs Andrew Munro 7/5/18, 4:35 PM
    • Merge pull request #1 from skybet/feature/validation-ordering-and-zero-value-ptrs Andrew Munro* 7/3/18, 1:19 PM
    • Ensuring order on validation rules. Allowing nil values to pass validation. Passing input and validator tag to custom error messages Andrew Munro 7/3/18, 12:49 PM
    • (Enhancement) Validator: Validating contents of []int Marc Santiago 6/29/18, 9:52 PM
    • Validator: Adding more concrete base64 validation Marc Santiago 6/28/18, 7:29 PM
    • some simplications ferhat elmas 6/20/18, 1:47 PM
    • Add license scan report and status fossabot 5/22/18, 4:08 PM
    • Add hasWhitespace and hasWhitespaceOnly Jason Lam 4/13/18, 4:12 AM
    • Fix issue #269 - problem with parse urls with multiple underscores. Grzegorz Eliszewski 4/9/18, 10:46 PM
    • Fix struct validation when options include a numeric type check int, int8, int16....etc float32, float64 Jason Lam 4/7/18, 9:07 AM
    • Fix #266 alex.saskevich 3/19/18, 11:16 AM
    Source code(tar.gz)
    Source code(zip)
  • v7(Sep 6, 2017)

Owner
Alex Saskevich
Alex Saskevich
A fast, easy-of-use and dependency free custom mapping from .csv data into Golang structs

csvparser This package provides a fast and easy-of-use custom mapping from .csv data into Golang structs. Index Pre-requisites Installation Examples C

João Duarte 22 Nov 14, 2022
🧑‍💻 Go XML generator without Structs™

exml ??‍?? Go XML generator without Structs™ Package exml allows XML documents to be generated without the usage of structs or maps. It is not intende

Victor 3 Nov 15, 2022
csvplus extends the standard Go encoding/csv package with fluent interface, lazy stream operations, indices and joins.

csvplus Package csvplus extends the standard Go encoding/csv package with fluent interface, lazy stream processing operations, indices and joins. The

Maxim 67 Apr 9, 2022
Package strit introduces a new type of string iterator, along with a number of iterator constructors, wrappers and combinators.

strit Package strit (STRing ITerator) assists in development of string processing pipelines by providing a simple iteration model that allows for easy

Maxim 84 Jun 21, 2022
ByNom is a Go package for parsing byte sequences, suitable for parsing text and binary data

ByNom is a Go package for parsing byte sequences. Its goal is to provide tools to build safe byte parsers without compromising the speed or memo

Andrew Bashkatov 4 May 5, 2021
Package i18n is a middleware that provides internationalization and localization for Flamego

i18n Package i18n is a middleware that provides internationalization and localization for Flamego. Installation The minimum requirement of Go is 1.16.

Flamego 4 Dec 14, 2022
This package provides Go (golang) types and helper functions to do some basic but useful things with mxGraph diagrams in XML, which is most famously used by app.diagrams.net, the new name of draw.io.

Go Draw - Golang MX This package provides types and helper functions to do some basic but useful things with mxGraph diagrams in XML, which is most fa

null 2 Aug 30, 2022
A Package Searching and Installation tool for Go Projects.

Gosearch A Package Searching and Installation tool for Go Projects. Installation go install github.com/kinensake/[email protected] Usage gosearch <pack

Quan Quan 4 Dec 19, 2022
A golang package to work with Decentralized Identifiers (DIDs)

did did is a Go package that provides tools to work with Decentralized Identifiers (DIDs). Install go get github.com/ockam-network/did Example packag

Ockam 69 Nov 25, 2022
Genex package for Go

genex Genex package for Go Easy and efficient package to expand any given regex into all the possible strings that it can match. This is the code that

Alix Axel 68 Nov 2, 2022
A declarative struct-tag-based HTML unmarshaling or scraping package for Go built on top of the goquery library

goq Example import ( "log" "net/http" "astuart.co/goq" ) // Structured representation for github file name table type example struct { Title str

Andrew Stuart 222 Dec 12, 2022
Go (Golang) GNU gettext utilities package

Gotext GNU gettext utilities for Go. Features Implements GNU gettext support in native Go. Complete support for PO files including: Support for multil

Leonel Quinteros 363 Dec 18, 2022
htmlquery is golang XPath package for HTML query.

htmlquery Overview htmlquery is an XPath query package for HTML, lets you extract data or evaluate from HTML documents by an XPath expression. htmlque

null 551 Jan 4, 2023
A markdown renderer package for the terminal

go-term-markdown go-term-markdown is a go package implementing a Markdown renderer for the terminal. Note: Markdown being originally designed to rende

Michael Muré 253 Nov 25, 2022
Go package for syntax highlighting of code

syntaxhighlight Package syntaxhighlight provides syntax highlighting for code. It currently uses a language-independent lexer and performs decently on

Sourcegraph 253 Nov 18, 2022
A minimalistic emoji package for Go (golang)

emoji ?? ?? ?? emoji is a minimalistic emoji library for Go. It lets you use emoji characters in strings. Inspired by spatie/emoji Install ?? go get g

Enes Çakır 381 Dec 14, 2022
xmlquery is Golang XPath package for XML query.

xmlquery Overview xmlquery is an XPath query package for XML documents, allowing you to extract data or evaluate from XML documents with an XPath expr

null 324 Jan 1, 2023
Frongo is a Golang package to create HTML/CSS components using only the Go language.

Frongo Frongo is a Go tool to make HTML/CSS document out of Golang code. It was designed with readability and usability in mind, so HTML objects are c

Rewan_ 21 Jul 29, 2021
A dead simple parser package for Go

A dead simple parser package for Go V2 Introduction Tutorial Tag syntax Overview Grammar syntax Capturing Capturing boolean value Streaming Lexing Sta

Alec Thomas 2.8k Dec 30, 2022