Skip to content

Commit

Permalink
Merge pull request #145 from bluesuncorp/v5-development
Browse files Browse the repository at this point in the history
Add Exists Tag
  • Loading branch information
Dean Karn authored and Dean Karn committed Aug 4, 2015
2 parents 4b62444 + 627fcfa commit 98121ac
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 0 deletions.
8 changes: 8 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ Here is a list of the current built in validators:
inside of you program you know the struct will be valid, but need to
verify it has been assigned.
exists
Is a special tag without a validation function attached. It is used when a field
is a Pointer, Interface or Invalid and you wish to validate that it exists.
Example: want to ensure a bool exists if you define the bool as a pointer and
use exists it will ensure there is a value; couldn't use required as it would
fail when the bool was false. exists will fail is the value is a Pointer, Interface
or Invalid and is nil. (Usage: exists)
omitempty
Allows conditional validation, for example if a field is not set with
a value (Determined by the required validator) then other validation
Expand Down
32 changes: 32 additions & 0 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
mapErrMsg = "Field validation for \"%s\" failed on key \"%v\" with error(s): %s"
structErrMsg = "Struct:%s\n"
diveTag = "dive"
existsTag = "exists"
arrayIndexFieldName = "%s[%d]"
mapIndexFieldName = "%s[%v]"
)
Expand Down Expand Up @@ -722,7 +723,22 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f

for _, val := range cTag.keyVals {

// if (idxField.Kind() == reflect.Ptr || idxField.Kind() == reflect.Interface) && idxField.IsNil() {
// if val[0] == existsTag {
// if (cField.kind == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() {
// fieldErr = &FieldError{
// Field: name,
// Tag: val[0],
// Value: f,
// Param: val[1],
// }
// err = errors.New(fieldErr.Tag)
// }

// } else {

fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, val[0], val[1], name)
// }

if err == nil {
return nil
Expand All @@ -740,6 +756,18 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f
return fieldErr
}

if cTag.keyVals[0][0] == existsTag {
if (cField.kind == reflect.Ptr || cField.kind == reflect.Interface) && valueField.IsNil() {
return &FieldError{
Field: name,
Tag: cTag.keyVals[0][0],
Value: f,
Param: cTag.keyVals[0][1],
}
}
continue
}

if fieldErr, err = v.fieldWithNameAndSingleTag(val, current, f, cTag.keyVals[0][0], cTag.keyVals[0][1], name); err != nil {

fieldErr.Kind = cField.kind
Expand Down Expand Up @@ -981,6 +1009,10 @@ func (v *Validate) fieldWithNameAndSingleTag(val interface{}, current interface{
return nil, nil
}

// if key == existsTag {
// continue
// }

valFunc, ok := v.validationFuncs[key]
if !ok {
panic(fmt.Sprintf("Undefined validation function on field %s", name))
Expand Down
31 changes: 31 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package validator

import (
"encoding/json"
"fmt"
"path"
"reflect"
Expand Down Expand Up @@ -231,6 +232,36 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e
EqualSkip(t, 2, val.Tag, expectedTag)
}

func TestExistsValidation(t *testing.T) {

jsonText := "{ \"truthiness2\": true }"

type Thing struct {
Truthiness *bool `json:"truthiness" validate:"exists,required"`
}

var ting Thing

err := json.Unmarshal([]byte(jsonText), &ting)
Equal(t, err, nil)
NotEqual(t, ting, nil)
Equal(t, ting.Truthiness, nil)

errs := validate.Struct(ting)
NotEqual(t, errs, nil)
AssertFieldError(t, errs, "Truthiness", "exists")

jsonText = "{ \"truthiness\": true }"

err = json.Unmarshal([]byte(jsonText), &ting)
Equal(t, err, nil)
NotEqual(t, ting, nil)
Equal(t, ting.Truthiness, true)

errs = validate.Struct(ting)
Equal(t, errs, nil)
}

func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {

var m map[string]string
Expand Down

0 comments on commit 98121ac

Please sign in to comment.