mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
improve empty value validation for required-with* patterns for package gvalid
This commit is contained in:
@ -9,6 +9,7 @@ package empty
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
// apiString is used for type assert api for String().
|
||||
@ -26,6 +27,11 @@ type apiMapStrAny interface {
|
||||
MapStrAny() map[string]interface{}
|
||||
}
|
||||
|
||||
type apiTime interface {
|
||||
Date() (year int, month time.Month, day int)
|
||||
IsZero() bool
|
||||
}
|
||||
|
||||
// IsEmpty checks whether given `value` empty.
|
||||
// It returns true if `value` is in: 0, nil, false, "", len(slice/map/chan) == 0,
|
||||
// or else it returns false.
|
||||
@ -80,6 +86,12 @@ func IsEmpty(value interface{}) bool {
|
||||
return len(value) == 0
|
||||
default:
|
||||
// Common interfaces checks.
|
||||
if f, ok := value.(apiTime); ok {
|
||||
if f == nil {
|
||||
return true
|
||||
}
|
||||
return f.IsZero()
|
||||
}
|
||||
if f, ok := value.(apiString); ok {
|
||||
if f == nil {
|
||||
return true
|
||||
|
||||
@ -220,6 +220,15 @@ func (t *Time) String() string {
|
||||
return t.Format("Y-m-d H:i:s")
|
||||
}
|
||||
|
||||
// IsZero reports whether t represents the zero time instant,
|
||||
// January 1, year 1, 00:00:00 UTC.
|
||||
func (t *Time) IsZero() bool {
|
||||
if t == nil {
|
||||
return true
|
||||
}
|
||||
return t.Time.IsZero()
|
||||
}
|
||||
|
||||
// Clone returns a new Time object which is a clone of current time object.
|
||||
func (t *Time) Clone() *Time {
|
||||
return New(t.Time)
|
||||
|
||||
@ -47,13 +47,11 @@ func (v *Validator) doCheck(key string, value interface{}, rules string, message
|
||||
// It converts value to string and then does the validation.
|
||||
var (
|
||||
// Do not trim it as the space is also part of the value.
|
||||
data = make(map[string]string)
|
||||
data = make(map[string]interface{})
|
||||
errorMsgArray = make(map[string]string)
|
||||
)
|
||||
if len(params) > 0 {
|
||||
for k, v := range gconv.Map(params[0]) {
|
||||
data[k] = gconv.String(v)
|
||||
}
|
||||
data = gconv.Map(params[0])
|
||||
}
|
||||
// Custom error messages handling.
|
||||
var (
|
||||
@ -150,7 +148,7 @@ func (v *Validator) doCheckBuildInRules(
|
||||
ruleKey string,
|
||||
rulePattern string,
|
||||
ruleItems []string,
|
||||
dataMap map[string]string,
|
||||
dataMap map[string]interface{},
|
||||
customMsgMap map[string]string,
|
||||
) (match bool, err error) {
|
||||
valueStr := gconv.String(value)
|
||||
@ -235,7 +233,7 @@ func (v *Validator) doCheckBuildInRules(
|
||||
// Values of two fields should be equal as string.
|
||||
case "same":
|
||||
if v, ok := dataMap[rulePattern]; ok {
|
||||
if strings.Compare(valueStr, v) == 0 {
|
||||
if strings.Compare(valueStr, gconv.String(v)) == 0 {
|
||||
match = true
|
||||
}
|
||||
}
|
||||
@ -250,7 +248,7 @@ func (v *Validator) doCheckBuildInRules(
|
||||
case "different":
|
||||
match = true
|
||||
if v, ok := dataMap[rulePattern]; ok {
|
||||
if strings.Compare(valueStr, v) == 0 {
|
||||
if strings.Compare(valueStr, gconv.String(v)) == 0 {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
package gvalid
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/internal/empty"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -14,7 +15,7 @@ import (
|
||||
|
||||
// checkRequired checks `value` using required rules.
|
||||
// It also supports require checks for `value` of type: slice, map.
|
||||
func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string, params map[string]string) bool {
|
||||
func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string, dataMap map[string]interface{}) bool {
|
||||
required := false
|
||||
switch ruleKey {
|
||||
// Required.
|
||||
@ -31,8 +32,8 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
for i := 0; i < len(array); {
|
||||
tk := array[i]
|
||||
tv := array[i+1]
|
||||
if v, ok := params[tk]; ok {
|
||||
if strings.Compare(tv, v) == 0 {
|
||||
if v, ok := dataMap[tk]; ok {
|
||||
if strings.Compare(tv, gconv.String(v)) == 0 {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
@ -51,8 +52,8 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
for i := 0; i < len(array); {
|
||||
tk := array[i]
|
||||
tv := array[i+1]
|
||||
if v, ok := params[tk]; ok {
|
||||
if strings.Compare(tv, v) == 0 {
|
||||
if v, ok := dataMap[tk]; ok {
|
||||
if strings.Compare(tv, gconv.String(v)) == 0 {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
@ -67,7 +68,7 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
required = false
|
||||
array := strings.Split(rulePattern, ",")
|
||||
for i := 0; i < len(array); i++ {
|
||||
if params[array[i]] != "" {
|
||||
if !empty.IsEmpty(dataMap[array[i]]) {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
@ -79,7 +80,7 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
required = true
|
||||
array := strings.Split(rulePattern, ",")
|
||||
for i := 0; i < len(array); i++ {
|
||||
if params[array[i]] == "" {
|
||||
if empty.IsEmpty(dataMap[array[i]]) {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
@ -91,7 +92,7 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
required = false
|
||||
array := strings.Split(rulePattern, ",")
|
||||
for i := 0; i < len(array); i++ {
|
||||
if params[array[i]] == "" {
|
||||
if empty.IsEmpty(dataMap[array[i]]) {
|
||||
required = true
|
||||
break
|
||||
}
|
||||
@ -103,7 +104,7 @@ func (v *Validator) checkRequired(value interface{}, ruleKey, rulePattern string
|
||||
required = true
|
||||
array := strings.Split(rulePattern, ",")
|
||||
for i := 0; i < len(array); i++ {
|
||||
if params[array[i]] != "" {
|
||||
if !empty.IsEmpty(dataMap[array[i]]) {
|
||||
required = false
|
||||
break
|
||||
}
|
||||
|
||||
@ -88,6 +88,72 @@ func Test_RequiredWith(t *testing.T) {
|
||||
t.AssertNE(err2, nil)
|
||||
t.AssertNE(err3, nil)
|
||||
})
|
||||
// time.Time
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
rule := "required-with:id,time"
|
||||
val1 := ""
|
||||
params1 := g.Map{
|
||||
"age": 18,
|
||||
}
|
||||
params2 := g.Map{
|
||||
"id": 100,
|
||||
}
|
||||
params3 := g.Map{
|
||||
"time": time.Time{},
|
||||
}
|
||||
err1 := gvalid.Check(val1, rule, nil, params1)
|
||||
err2 := gvalid.Check(val1, rule, nil, params2)
|
||||
err3 := gvalid.Check(val1, rule, nil, params3)
|
||||
t.Assert(err1, nil)
|
||||
t.AssertNE(err2, nil)
|
||||
t.Assert(err3, nil)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
rule := "required-with:id,time"
|
||||
val1 := ""
|
||||
params1 := g.Map{
|
||||
"age": 18,
|
||||
}
|
||||
params2 := g.Map{
|
||||
"id": 100,
|
||||
}
|
||||
params3 := g.Map{
|
||||
"time": time.Now(),
|
||||
}
|
||||
err1 := gvalid.Check(val1, rule, nil, params1)
|
||||
err2 := gvalid.Check(val1, rule, nil, params2)
|
||||
err3 := gvalid.Check(val1, rule, nil, params3)
|
||||
t.Assert(err1, nil)
|
||||
t.AssertNE(err2, nil)
|
||||
t.AssertNE(err3, nil)
|
||||
})
|
||||
// gtime.Time
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type UserApiSearch struct {
|
||||
Uid int64 `json:"uid"`
|
||||
Nickname string `json:"nickname" v:"required-with:Uid"`
|
||||
StartTime *gtime.Time `json:"start_time" v:"required-with:EndTime"`
|
||||
EndTime *gtime.Time `json:"end_time" v:"required-with:StartTime"`
|
||||
}
|
||||
data := UserApiSearch{
|
||||
StartTime: nil,
|
||||
EndTime: nil,
|
||||
}
|
||||
t.Assert(gvalid.CheckStruct(data, nil), nil)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type UserApiSearch struct {
|
||||
Uid int64 `json:"uid"`
|
||||
Nickname string `json:"nickname" v:"required-with:Uid"`
|
||||
StartTime *gtime.Time `json:"start_time" v:"required-with:EndTime"`
|
||||
EndTime *gtime.Time `json:"end_time" v:"required-with:StartTime"`
|
||||
}
|
||||
data := UserApiSearch{
|
||||
StartTime: nil,
|
||||
EndTime: gtime.Now(),
|
||||
}
|
||||
t.AssertNE(gvalid.CheckStruct(data, nil), nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_RequiredWithAll(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user