Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a5d0ef3
update doc.go, some v5 specific notes were left.
Jul 23, 2015
aef21d4
Update Benchmarks
Jul 23, 2015
781f596
Merge pull request #120 from joeybloggs/v6-development
Jul 23, 2015
b9cdaa4
Merge pull request #121 from bluesuncorp/v6-development
Jul 23, 2015
201c892
Split out assertions and put in external repo
Jul 23, 2015
c59a51f
Merge pull request #122 from joeybloggs/v6-development
Jul 23, 2015
ea0db1f
Add single Field validation example
Jul 27, 2015
f462515
Merge pull request #123 from joeybloggs/v6-development
Jul 27, 2015
54927e9
Merge pull request #124 from bluesuncorp/v6-development
Jul 27, 2015
e078205
Update Required & Invalid logic
Jul 27, 2015
a563180
Merge pull request #126 from joeybloggs/v6-development
Jul 27, 2015
c000117
Merge pull request #127 from bluesuncorp/v6-development
Jul 27, 2015
bd16331
Add ip, ipv4 and ipv6 validators
Jul 28, 2015
143b21e
Add mac validator
Jul 28, 2015
a7e8a12
Merge pull request #128 from joeybloggs/v6-development
Jul 28, 2015
55e8c8d
Merge pull request #129 from bluesuncorp/v6-development
Jul 28, 2015
d363ed3
Add handling of custom types
Jul 31, 2015
a05046f
Merge pull request #135 from joeybloggs/v6-development
Jul 31, 2015
d802346
Merge pull request #136 from bluesuncorp/v6-development
Jul 31, 2015
790122c
Update simple.go
Jul 31, 2015
6a8ed56
Update simple.go file && README
Jul 31, 2015
32910f8
Merge pull request #137 from joeybloggs/v6-development
Jul 31, 2015
048d7b8
Merge branch 'v6-development' into v6
Jul 31, 2015
7c84489
Added RegisterCustomTypeFunc method and usage example.
Jul 31, 2015
d2ea21a
Add RegisterCustomTypeFunc for easier adding of CustomTypeFunc
Aug 2, 2015
442b210
Merge pull request #140 from joeybloggs/v6-development
Aug 2, 2015
a13509d
Merge pull request #141 from bluesuncorp/v6-development
Aug 2, 2015
f8fd456
Update README.md
Aug 2, 2015
7e97fcf
Add exists tag
Aug 4, 2015
3f5b785
Merge pull request #144 from joeybloggs/v6-development
Aug 4, 2015
0cd5e89
Merge pull request #146 from bluesuncorp/v6-development
Aug 4, 2015
50f0798
Run gofmt -s -w . on code
Aug 4, 2015
494e136
Merge pull request #147 from joeybloggs/v6-development
Aug 4, 2015
c62ee7c
Merge pull request #148 from bluesuncorp/v6-development
Aug 4, 2015
844f5f4
Updated Panic Tests after updates to assertion library
Aug 17, 2015
8a9ed1f
Merge pull request #151 from joeybloggs/v6-development
Aug 17, 2015
6df82fd
Merge pull request #152 from bluesuncorp/v6-development
Aug 17, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 92 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ It has the following **unique** features:

- Cross Field and Cross Struct validations.
- Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.
- Handles type interface by determining it's underlying type prior to validation.
- Handles type interface by determining it's underlying type prior to validation.
- Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29)

Installation
------------
Expand All @@ -34,7 +35,9 @@ Usage and documentation

Please see http://godoc.org/gopkg.in/bluesuncorp/validator.v6 for detailed usage docs.

##### Example:
##### Examples:

Struct & Field validation
```go
package main

Expand Down Expand Up @@ -73,6 +76,12 @@ func main() {

validate = validator.New(config)

validateStruct()
validateField()
}

func validateStruct() {

address := &Address{
Street: "Eavesdown Docks",
Planet: "Persphone",
Expand Down Expand Up @@ -109,6 +118,71 @@ func main() {

// save user to database
}

func validateField() {
myEmail := "joeybloggs.gmail.com"

errs := validate.Field(myEmail, "required,email")

if errs != nil {
fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
return
}

// email ok, move on
}
```

Custom Field Type
```go
package main

import (
"database/sql"
"database/sql/driver"
"fmt"
"reflect"

"gopkg.in/bluesuncorp/validator.v6"
)

// DbBackedUser User struct
type DbBackedUser struct {
Name sql.NullString `validate:"required"`
Age sql.NullInt64 `validate:"required"`
}

func main() {

config := validator.Config{
TagName: "validate",
ValidationFuncs: validator.BakedInValidators,
}

validate := validator.New(config)

// register all sql.Null* types to use the ValidateValuer CustomTypeFunc
validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})

x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
errs := validate.Struct(x)

if len(errs) > 0 {
fmt.Printf("Errs:\n%+v\n", errs)
}
}

// ValidateValuer implements validator.CustomTypeFunc
func ValidateValuer(field reflect.Value) interface{} {
if valuer, ok := field.Interface().(driver.Valuer); ok {
val, err := valuer.Value()
if err == nil {
return val
}
// handle the error how you want
}
return nil
}
```

Benchmarks
Expand All @@ -120,12 +194,22 @@ hurt parallel performance too much.
```go
$ go test -cpu=4 -bench=. -benchmem=true
PASS
BenchmarkField-4 5000000 314 ns/op 16 B/op 1 allocs/op
BenchmarkFieldOrTag-4 500000 2425 ns/op 20 B/op 2 allocs/op
BenchmarkStructSimple-4 500000 3117 ns/op 553 B/op 14 allocs/op
BenchmarkStructSimpleParallel-4 1000000 1149 ns/op 553 B/op 14 allocs/op
BenchmarkStructComplex-4 100000 19580 ns/op 3230 B/op 102 allocs/op
BenchmarkStructComplexParallel-4 200000 6686 ns/op 3232 B/op 102 allocs/op
BenchmarkFieldSuccess-4 5000000 318 ns/op 16 B/op 1 allocs/op
BenchmarkFieldFailure-4 5000000 316 ns/op 16 B/op 1 allocs/op
BenchmarkFieldCustomTypeSuccess-4 3000000 492 ns/op 32 B/op 2 allocs/op
BenchmarkFieldCustomTypeFailure-4 2000000 843 ns/op 416 B/op 6 allocs/op
BenchmarkFieldOrTagSuccess-4 500000 2384 ns/op 20 B/op 2 allocs/op
BenchmarkFieldOrTagFailure-4 1000000 1295 ns/op 384 B/op 6 allocs/op
BenchmarkStructSimpleSuccess-4 1000000 1175 ns/op 24 B/op 3 allocs/op
BenchmarkStructSimpleFailure-4 1000000 1822 ns/op 529 B/op 11 allocs/op
BenchmarkStructSimpleCustomTypeSuccess-4 1000000 1302 ns/op 56 B/op 5 allocs/op
BenchmarkStructSimpleCustomTypeFailure-4 1000000 1847 ns/op 577 B/op 13 allocs/op
BenchmarkStructSimpleSuccessParallel-4 5000000 339 ns/op 24 B/op 3 allocs/op
BenchmarkStructSimpleFailureParallel-4 2000000 733 ns/op 529 B/op 11 allocs/op
BenchmarkStructComplexSuccess-4 200000 7104 ns/op 368 B/op 30 allocs/op
BenchmarkStructComplexFailure-4 100000 11996 ns/op 2861 B/op 72 allocs/op
BenchmarkStructComplexSuccessParallel-4 1000000 2252 ns/op 368 B/op 30 allocs/op
BenchmarkStructComplexFailureParallel-4 300000 4691 ns/op 2862 B/op 72 allocs/op
```

How to Contribute
Expand Down
36 changes: 32 additions & 4 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package validator

import (
"fmt"
"net"
"net/url"
"reflect"
"strconv"
Expand Down Expand Up @@ -64,6 +65,35 @@ var BakedInValidators = map[string]Func{
"latitude": isLatitude,
"longitude": isLongitude,
"ssn": isSSN,
"ipv4": isIPv4,
"ipv6": isIPv6,
"ip": isIP,
"mac": isMac,
}

func isMac(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
_, err := net.ParseMAC(field.String())
return err == nil
}

func isIPv4(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {

ip := net.ParseIP(field.String())

return ip != nil && ip.To4() != nil
}

func isIPv6(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
ip := net.ParseIP(field.String())

return ip != nil && ip.To4() == nil
}

func isIP(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {

ip := net.ParseIP(field.String())

return ip != nil
}

func isSSN(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
Expand Down Expand Up @@ -403,10 +433,8 @@ func isAlpha(topStruct reflect.Value, currentStruct reflect.Value, field reflect
func hasValue(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {

switch fieldKind {

case reflect.Slice, reflect.Map, reflect.Array:
return !field.IsNil() && int64(field.Len()) > 0

case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
return !field.IsNil()
default:
return field.IsValid() && field.Interface() != reflect.Zero(fieldType).Interface()
}
Expand Down
Loading