allow custom validation rule validate empty or nil values

This commit is contained in:
Jack 2020-10-21 00:08:36 +08:00
parent 561a541fa1
commit 43441a8218
4 changed files with 64 additions and 4 deletions

View File

@ -87,20 +87,27 @@ func CheckMap(params interface{}, rules interface{}, messages ...CustomMsg) *Err
if v, ok := data[key]; ok {
value = v
}
// It checks each rule and its value in loop.
if e := doCheck(key, value, rule, customMsgs[key], data); e != nil {
_, item := e.FirstItem()
// ===========================================================
// If value is nil or empty string and has no required* rules,
// clear the error message.
// Only in map and struct validations, if value is nil or empty
// string and has no required* rules, it clears the error message.
// ===========================================================
if gconv.String(value) == "" {
required := false
// rule => error
for k := range item {
// Default required rules.
if _, ok := mustCheckRulesEvenValueEmpty[k]; ok {
required = true
break
}
// Custom rules are also required in default.
if _, ok := customRuleFuncMap[k]; ok {
required = true
break
}
}
if !required {
continue

View File

@ -149,20 +149,27 @@ func CheckStruct(object interface{}, rules interface{}, messages ...CustomMsg) *
if v, ok := params[key]; ok {
value = v
}
// It checks each rule and its value in loop.
if e := doCheck(key, value, rule, customMessage[key], params); e != nil {
_, item := e.FirstItem()
// ===========================================================
// If value is nil or empty string and has no required* rules,
// clear the error message.
// Only in map and struct validations, if value is nil or empty
// string and has no required* rules, it clears the error message.
// ===========================================================
if value == nil || gconv.String(value) == "" {
required := false
// rule => error
for k := range item {
// Default required rules.
if _, ok := mustCheckRulesEvenValueEmpty[k]; ok {
required = true
break
}
// Custom rules are also required in default.
if _, ok := customRuleFuncMap[k]; ok {
required = true
break
}
}
if !required {
continue

View File

@ -16,6 +16,7 @@ type RuleFunc func(rule string, value interface{}, message string, params map[st
var (
// customRuleFuncMap stores the custom rule functions.
// map[Rule]RuleFunc
customRuleFuncMap = make(map[string]RuleFunc)
)

View File

@ -106,3 +106,48 @@ func Test_CustomRule2(t *testing.T) {
t.Assert(err, nil)
})
}
func Test_CustomRule_AllowEmpty(t *testing.T) {
rule := "allow-empty-str"
err := gvalid.RegisterRule(rule, func(rule string, value interface{}, message string, params map[string]interface{}) error {
s := gconv.String(value)
if len(s) == 0 || s == "gf" {
return nil
}
return errors.New(message)
})
gtest.Assert(err, nil)
// Check.
gtest.C(t, func(t *gtest.T) {
errStr := "error"
t.Assert(gvalid.Check("", rule, errStr).String(), "")
t.Assert(gvalid.Check("gf", rule, errStr).String(), "")
t.Assert(gvalid.Check("gf2", rule, errStr).String(), errStr)
})
// Error with struct validation.
gtest.C(t, func(t *gtest.T) {
type T struct {
Value string `v:"uid@allow-empty-str#自定义错误"`
Data string `p:"data"`
}
st := &T{
Value: "",
Data: "123456",
}
err := gvalid.CheckStruct(st, nil)
t.Assert(err.String(), "")
})
// No error with struct validation.
gtest.C(t, func(t *gtest.T) {
type T struct {
Value string `v:"uid@allow-empty-str#自定义错误"`
Data string `p:"data"`
}
st := &T{
Value: "john",
Data: "123456",
}
err := gvalid.CheckStruct(st, nil)
t.Assert(err.String(), "自定义错误")
})
}