Merge pull request #145 from bluesuncorp/v5-development

Add Exists Tag
v5 v5.11
Dean Karn 9 years ago
commit 98121ac23f
  1. 8
      doc.go
  2. 32
      validator.go
  3. 31
      validator_test.go

@ -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

@ -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]"
)
@ -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
@ -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
@ -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))

@ -1,6 +1,7 @@
package validator
import (
"encoding/json"
"fmt"
"path"
"reflect"
@ -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

Loading…
Cancel
Save