asaskevich / govalidator Goto Github PK
View Code? Open in Web Editor NEW[Go] Package of validators and sanitizers for strings, numerics, slices and structs
License: MIT License
[Go] Package of validators and sanitizers for strings, numerics, slices and structs
License: MIT License
Hi. Thanks for this awesome project!
I just notice that a home page URL of Wikipedia (which contains Unicode characters) can not pass the validation: https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5
This really should not happen, as DialString is supposed to check host:port
combinations.
I am working on this and will send a PR asap.
I would like to use govalidator to do database validation, like checking the uniqueness.
Something like that:
govalidator.TagMap["unique"] = govalidator.Validator(func(field string, s interface{}) bool {
return CheckUniquenessInDB(s, field)
})
Do you see a simple solution ?
I am wondering how to get errors for specific fields for the purpose of showing invalid input on a form. As far as I can gather ValidateStruct just returns a normal error object that is a string of all of the errors. Is there a way to get the errors for a specific field or am I missing something.
Thanks for any help.
Hi,
I have a case where govalidator does not check a tag on of a nested struct:
where Owner ID of both structs (top in Notification and the one under Profile) is declared as:
OwnerID string `bson:"owner_id" json:"owner_id" valid:"uuid, length(36|36)"`
I.e. this test would fail.
Also,
I noticed validation is not working on private properties.
For example, this one will work
pInv := Profile{
OwnerID: "invalid uuid",
}
while with a private ownerID property, won't:
pInv := Profile{
ownerID: "invalid uuid",
}
Thank you
D.
If I am parsing XML I need to have the XML map on the struct.
// Enrollment - Enrollment record
type Enrollment struct {
MasterEfin string `xml:"MasterEfin"`
EFIN string `xml:"EFIN"`
TransmitterID string `xml:"TransmitterId"`
ProcessingYear string `xml:"ProcessingYear"`
OfficeInfo OfficeInfo `xml:"OfficeInfo"`
OwnerInformation OwnerInformation `xml:"OwnerInformation"`
EFINOwnerInfo EFINOwnerInfo `xml:"EFINOwnerInfo"`
PriorYearInfo PriorYearInfo `xml:"PriorYearInfo"`
TransactionDate string `xml:"TransactionDate"`
}
I'd like to read in XML and use govalidator to validate the fields before I save the data into our database.
I can't add the validation information - so do I need to move the data into a new struct to validate it? Is that the easiest method?
type validEnrollment struct {
MasterEfin string `valid:"alphanum,required"`
EFIN string `valid:"alphanum,required"`
TransmitterID string `valid:"alphanum,required"`
ProcessingYear string `valid:"alphanum,required"`
OfficeInfo OfficeInfo
OwnerInformation OwnerInformation
EFINOwnerInfo EFINOwnerInfo
PriorYearInfo PriorYearInfo
TransactionDate string
}
Suggestions? I am still learning go so be gentle. ;)
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:
var intValidator
)Snap-CI seems to think this repo is a Ruby repo and tries to run the tests with rake.
See https://snap-ci.com/asaskevich/govalidator/pull/8/logs/defaultPipeline/1/Travis.
On some functions empty string is valid and returns TRUE on others it is not and returns FALSE.
First of all empty string returns FALSE on IsASCII(str string)__.
On *IsAlpha(str string) empty string returns FALSE, but on IsUTFLetter(str string) it returns TRUE
IsAlphanumeric("") returns FALSE
IsUTFLetterNumeric("") returns TRUE
IsNumeric("") returns FALSE
IsUTFNumeric("") returns TRUE
IsUTFDigit("") returns TRUE
IsLowerCase("") returns TRUE
IsUpperCase("") returns TRUE
IsFullWidth("") returns FALSE
IsHalfWidth("") returns FALSE
IsVariableWidth("") returns FALSE
As of my own opinion every character in empty string is a valid Alphanumeric, Numeric, UTFNumeric, UTFDigit, UpperCase, LowerCase, FullWidth, HalfWidth, VariableWidth, Alpha and UTFLetter character, as there is no character in empty string.
So shouldn't these functions all return TRUE on empty string?
I beleive the ToString() example in the README.md file needs to be fixed. when I tried, ToString() is returning only one parameter, which is string type. the example is expecting a second parameter, which is incorrect so this example needs to be corrected.
It appears int
is no longer a valid struct validator. I'm getting a message "Field: Validator int doesn't supported Kind int", which is strange.
You can reproduce by adding ,int
to line 1572 of validator_test.go
.
I could be way off, too, let me know if you want a more proper test case or to dig in further.
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.
It looks like some of this valid URLs marked as invalid by IsURL:
http://www.foobar.com/~foobar
http://foobar.com/t$-_.+!*\'(),
http://foobar.com#baz=qux
Hi,
Thanks for the awesome work on the package.
I want to ask you if you'd be ok with me adding a custom validators option to the package so that other people could use the validators with this package without going to the same pains of doing the field tag reading and so on.
Thank you.
http://www.example.com - OK
http://me.example.com - "http://me.example.com does not validate as url"
http://www.me.example.com - "http://www.me.example.com does not validate as url"
looks like there's a problem with subdomains which are different from www in the regexp...
This is with go 1.5.
package main
import (
"fmt"
"github.com/asaskevich/govalidator"
)
type Foo struct {
Name string `valid:"required"`
Type string `valid:"required"`
}
type Bar struct {
F Foo `valid:"required"`
}
func main() {
f := Bar{Foo{Type: "Foo"}}
result, err := govalidator.ValidateStruct(f)
if err != nil {
errors := govalidator.ErrorsByField(err)
fmt.Println(errors)
}
println(result)
}
➜ val go run main.go
panic: interface conversion: error is govalidator.Errors, not govalidator.Error
goroutine 1 [running]:
github.com/asaskevich/govalidator.ErrorsByField(0x708598, 0xc8201a3960, 0xc8201a3800)
/Users/matthew/go/src/github.com/asaskevich/govalidator/validator.go:883 +0x22b
main.main()
/Users/matthew/tmp/val/main.go:21 +0xf0
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1696 +0x1
exit status 2
Hi,
Quite often structs are loaded from json using the standard json go functionality, i.e a struct definition below is quite common:
type User struct {
FirstName string `json:"first_name" valid:"required"`
LastName string `json:"first_name" valid:"required"`
}
Assuming we use the govalidator to validate our struct, it would be very handy to have the option to be able to specify that we would rather have error messages report fields names based on the json field name rather than the struct name per se.
i.e. instead of
FirstName: non zero value required
rather
first_name: non zero value required
Is this possible?
Applying multiple custom tags to a struct property only invokes the first custom validator. For example, given following scenario:
func init() {
govalidator.CustomTypeTagMap["sqlalphanum"] = govalidator.CustomTypeValidator(func(i interface{}) bool {
switch v := i.(type) {
case sql.NullString:
return govalidator.IsAlphanumeric(v.String)
}
return false
})
govalidator.CustomTypeTagMap["sqlrequired"] = govalidator.CustomTypeValidator(func(i interface{}) bool {
switch v := i.(type) {
case sql.NullString:
return v.Valid
}
return false
})
}
type User struct {
Name sql.NullString `valid:"sqlrequired,sqlalphanum"`
City sql.NullString `valid:"sqlalphanum"`
}
govalidator.ValidateStruct()
on user object will invoke only sqlrequired
custom validator for Name
property.
Looking at the source (https://github.com/asaskevich/govalidator/blob/master/validator.go#L688), it indeed returns as soon as a custom validator is found. Shouldn't it decide validity after invoking all custom validators (if more than one)?
Compile regexes at build time instead of at every function call (consts.go
).
I tried several options:
valid:"length(min)=1"
valid:"length(min):1"
valid:"length(1|255)"
valid:"length(1,255)"
This never returns any error nor does it catch an empty input. Can someone help me out?
I am not sure if I am doing this the right way, but
println(govalidator.IsURL(http://user@pass:domain.com/path/page
))
return false for me. Shouldn't this be true? Furthermore, I get the following results:
println(govalidator.IsURL(http://www.domain.com
)) returns true
println(govalidator.IsURL(http://blog.domain.com
)) returns false
It's easier for localization if the error messages are codes or similar, it could be numeric codes(exporting the constants) or string codes like "email.invalid"
, "name.required"
, "password.length"
, etc.
I have used govalidator extensively without issues. However, I have never used the ValidateStruct
method, until today. For some strange reason it never validates my struct. Here is a snippet from my code:
newUser := &struct {
Name string `valid:"-"`
Mobile string `valid:"numeric,required`
}{Name: "legal", Mobile: "illegal"}
result, err := govalidator.ValidateStruct(newUser)
log.Printf("result: %+v\n", result)
log.Printf("err: %+v\n", err)
result
is always true
and err
is always nil
. No matter what my struct fields contain it returns the same thing. Looking in the source I see nothing wrong with the ValidateStruct
method. Someone please verify if I am doing something wrong. This has been driving me nuts all afternoon.
I am using go 1.5.1 and the latest version of govalidator from master
Do you plan on supporting (or accepting patches) for other types than strings?
I want to look at the source of SafeFileName function.
but I cannot find the source in this repository.
and I tested the function in my go project. It's working.
by the way, the reason why i want to look into that function is that the function is too strict in my opinion.
What kind of rules that function followed? Can I have a reference of it?
Getting "undefined" error when trying to use validators from the numerics.go.
I tried for:
IsNonNegative
InRange
The tests could be made a bit more readable. There are a few problems now:
t.Log(…)
+ t.FailNow()
should be converted to a t.Fatal()
.t.Error()
or t.Errorf()
instead of t.Fatal()
or t.FailNow()
.for i := …
style for-loops.t.Parallel()
at the top of each test case).-race
flag on Wercker.As an example, here is how a test case should be changed:
func TestIsAlpha(t *testing.T) {
tests := []string{"", " fooo ", "abc1", "abc", "ABC", "FoObAr"}
expected := []bool{false, false, false, true, true, true}
for i := 0; i < len(tests); i++ {
result := IsAlpha(tests[i])
if result != expected[i] {
t.Log("Case ", i, ": expected ", expected[i], " when result is ", result)
t.FailNow()
}
}
}
func TestIsAlpha(t *testing.T) {
t.Parallel()
for input, expected := range map[string]bool{
"": false,
" foooo ": false,
"abc1": false,
"abc": true,
"ABC": true,
"FoObAr": true,
} {
if result := IsAlpha(input); result != expected {
t.Errorf("Expected IsAlpha(%q) to be %v, got %v", input, expected, result)
}
}
}
/home/me/file.txt
is valid in unix based OSes.The tests seem to depend on a global state. They sometimes fail with the following error message:
--- FAIL: TestEscape (0.00 seconds)
utils_test.go:155: Case 0 : expected <img alt="foo&bar"> when result is &lt;img alt=&quot;foo&bar&quot;&gt;
Add ip
tag, map it to IsIP
.
I wanna validate the slice length to use govalidator as a JSON schema checker. JSON schema has maxItems and minItems validator.
http://json-schema.org/latest/json-schema-validation.html#anchor42
Isn't it usual case to check the length of slice if we write a RESTful web API? Do you have a plan to implement this feature or some other way to do this?
I think it makes more sense to return []error
from govalidator.ValidateStruct
since a struct can have many errors and that should be represented as a collection of errors. And it also makes my life easier because one lib I'm using expects a slice of error
IsURL validator is not working with urls which contains subdomains.
e.g The url "https://s3.amazonaws.com/bucket/5113a82b-06b6-418c-fd34/eae2b303-a7b2-4707-b04a" is not matching with IsURL method.
Any ideas? Maybe include this into URL string which contain url regular expression?
Thanks in advance.
Would phone number validation be a welcome pull request?
I think it can be usful...
I took a look in the go lib , they have such method :
func isDomainName(s string) bool {
// See RFC 1035, RFC 3696.
if len(s) == 0 {
return false
}
if len(s) > 255 {
return false
}
last := byte('.')
ok := false // Ok once we've seen a letter.
partlen := 0
for i := 0; i < len(s); i++ {
c := s[i]
switch {
default:
return false
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_':
ok = true
partlen++
case '0' <= c && c <= '9':
// fine
partlen++
case c == '-':
// Byte before dash cannot be dot.
if last == '.' {
return false
}
partlen++
case c == '.':
// Byte before dot cannot be dot, dash.
if last == '.' || last == '-' {
return false
}
if partlen > 63 || partlen == 0 {
return false
}
partlen = 0
}
last = c
}
if last == '-' || partlen > 63 {
return false
}
return ok
}
If you test the URL regex with a plain string as foo
it returns true when it shouldn't as its not a valid URL.
This might be useful in a number of contexts, for example:
I was thinking of something like the TagMap, e.g:
govalidators.StructMap["passwordsEqual"] = govalidators.StructValidator(func(s interface{}, str string) bool {
return str == i.(MyStruct).PasswordCheck
})
These validators would then be run under ValidateStruct.
type M map[string]interface{}
type T struct {
Map M `json:"m" valid:"-"`
}
b := []byte(`{"m":{"key":"value"}}`)
var t T
if err := json.Unmarshal(b, &t); err != nil {
// Handle unmarshal error.
}
result, err := valid.ValidateStruct(&t) // err = "function only accepts structs; got reflect.Value;"
This source of this problem is around this line:
Line 602 in 500e5aa
I think govalidator shouldn't recurse-validate into maps if valid:"-"
struct tag is present or valid:"..."
tag is missing.
as title :-)
I wish suggest use gopkg.in to avoid broke third-party implementations
Thanks!
I see the unit tests do pass but they seem to avoid this case.
This prints "true" but I believe it should show an error because of the empty Title value.
package main
import "github.com/asaskevich/govalidator"
type Post struct {
Title string `valid:"required,ascii"`
}
func main() {
post := &Post{Title: ""}
result, err := govalidator.ValidateStruct(post)
if err != nil {
println("error: " + err.Error())
}
println(result)
}
tmp,_ := v.ToString(fmt.Sprint(1))
Expect(v.IsInt(tmp)).To(BeTrue(),"v.ToString makes double quotes, IsInt fails to recognize int string")
Looking at issue #48, I think adding more documentation (not only in the code, but also on the README) and adding specification may helps to avoid misunderstandings on how a validation functions works/should work. A clear and good documentation and specification also may shows us cases that should be tested but currently are not. Or whether the current implementation is good or not.
The specification should be based on the idea of the validation functions and not on the current implementation. This may leads to changes in the current validation functions implementation and documentation but also leads to more reasonable and understandable validation functions.
I tried to add documentation using the information of how the validation functions works. But that only led me to some "inconsistent" behavior. E.g. in some "Is"-Numeric validation function leading zeros are valid, in some not. Sometime empty string is valid, sometimes not.
But these are not by any meaning bugs! The question is, what was the intention of the validation function (what is the specification).
Hello,
I recently updated your package and I am getting an strange issue !
I get this :
Limit: Validator int doesn't supported Kind int;
When I try to validate this struct :
var Form struct {
Offset int `valid:"int"`
Limit int `valid:"int"`
}
And If I remove Limit Validator the issue disappear.
Thanks !
This url is treated as a false url
After all govalidator is kind of the frontline for any type of input and probably our tests are not perfectly checking for all possible types of input. So maybe adding some fuzzing tests could help to improve the quality of the validators.
here are two good looking fuzzing libraries:
looks complex but has many features
https://github.com/zimmski/tavor
looks simple and easy to implement.
https://github.com/google/gofuzz
It would be neat to have the errors returned as JSON instead of a string.
Given
type Profile struct {
Email string `json:"email" valid:”required,email”`
}
type User struct {
Profile Profile `json:"profile" valid:”…”`
}
you get errors back like
{
“profile”: {
“email”: [
“non zero value required",
"does not validate as email"
]
}
}
Would be nice if there's a way to provide custom error messages when validating structs - https://github.com/asaskevich/govalidator#validatestruct-2
Using this code from your docs:
type Post struct {
Title string `valid:"alphanum,required"`
Message string `valid:"duck,ascii"`
AuthorIP string `valid:"ipv4"`
Date string `valid:"-"`
}
result, err := govalidator.ValidateStruct(post)
if err != nil {
println("error: " + err.Error())
}
println(result)
Is there a way to detect specifically which field in the struct failed the validation test? I want to be able to return a message based on the particular field that failed validation.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.