Skip to content

Commit

Permalink
fix: #120 Error validating on multi nested struct
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Mar 3, 2022
1 parent ed42e34 commit 4dc93ac
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 22 deletions.
33 changes: 15 additions & 18 deletions data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,12 +328,7 @@ func (d *StructData) parseRulesFromTag(v *Validation) {
// preferred to use label tag name. eg: `label:"display name"`
// and then use field output name. eg: `json:"user_name"`
if gOpt.LabelTag != "" {
lName := fv.Tag.Get(gOpt.LabelTag)
if lName == "" {
lName = outName
}

v.trans.addLabelName(name, lName)
v.trans.addLabelName(name, fv.Tag.Get(gOpt.LabelTag))
}

// load custom error messages.
Expand Down Expand Up @@ -481,10 +476,9 @@ func (d *StructData) Get(field string) (interface{}, bool) {
var fv reflect.Value
field = strutil.UpperFirst(field)

// want get sub struct field.
// want to get sub struct field.
if strings.ContainsRune(field, '.') {
fieldNodes := strings.Split(field, ".")

if len(fieldNodes) < 2 {
return nil, false
}
Expand All @@ -505,35 +499,38 @@ func (d *StructData) Get(field string) (interface{}, bool) {
}

fieldNodes = fieldNodes[1:]
lastIndex := len(fieldNodes) - 1
// lastIndex := len(fieldNodes) - 1

for i, fieldNode := range fieldNodes {
fieldNode = strings.ReplaceAll(fieldNode, "\"", "") // for strings as keys
kind = fv.Type().Kind()
for _, fieldNode := range fieldNodes {
// fieldNode = strings.ReplaceAll(fieldNode, "\"", "") // for strings as keys

kind := fv.Type().Kind()
switch kind {
case reflect.Array, reflect.Slice:
index, _ := strconv.Atoi(fieldNode)
fv = fv.Index(index)
case reflect.Map:
fv = fv.MapIndex(reflect.ValueOf(fieldNode))
default:
case reflect.Struct:
fv = fv.FieldByName(fieldNode)
default: // no sub-value
return nil, false
}

fv = removeValuePtr(fv)

if !fv.IsValid() {
return nil, false
}

if IsZero(fv) || (fv.Kind() == reflect.Ptr && fv.IsNil()) {
kind = fv.Type().Kind()
// if IsZero(fv) || (fv.Kind() == reflect.Ptr && fv.IsNil()) {
if fv.Kind() == reflect.Ptr && fv.IsNil() {
return nil, false
}

if i < lastIndex && fv.Type().Kind() != reflect.Struct {
return nil, false
}
// if i < lastIndex && fv.Type().Kind() != reflect.Struct {
// return nil, false
// }
}

d.fieldNames[field] = fieldAtSubStruct
Expand Down
29 changes: 29 additions & 0 deletions issues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,3 +684,32 @@ func TestIssue_111(t *testing.T) {
assert.Contains(t, v.Errors.String(), "密码 ")
assert.Contains(t, v.Errors.String(), " 重复密码")
}

// https://github.com/gookit/validate/issues/120
func TestIssue_120(t *testing.T) {
type ThirdStruct struct {
Val string `json:"val" validate:"required"`
}
type SecondStruct struct {
Third []ThirdStruct `json:"third" validate:"slice"`
}
type MainStruct struct {
Second []SecondStruct `json:"second" validate:"slice"`
}

v := validate.Struct(&MainStruct{
Second: []SecondStruct{
{
Third: []ThirdStruct{
{
Val: "hello",
},
},
},
},
})

ok := v.Validate()
dump.Println(v.Errors)
assert.True(t, ok)
}
4 changes: 2 additions & 2 deletions messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,12 @@ func (t *Translator) HasLabel(field string) bool {
return ok
}

// LabelName get in the t.labelMap
// LabelName get label name from the t.labelMap, fallback get output name from t.fieldMap
func (t *Translator) LabelName(field string) string {
if label, ok := t.labelMap[field]; ok {
field = label
}
return field
return t.FieldName(field)
}

// AddMessages data to translator
Expand Down
4 changes: 3 additions & 1 deletion validating.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (r *Rule) Apply(v *Validation) (stop bool) {
return
}

// has beforeFunc and it return FALSE, skip validate
// has beforeFunc and it returns FALSE, skip validate
if r.beforeFunc != nil && !r.beforeFunc(v) {
return
}
Expand Down Expand Up @@ -329,6 +329,8 @@ func callValidator(v *Validation, fm *funcMeta, field string, val interface{}, a
ok = Between(val, args[0].(int64), args[1].(int64))
case "isJSON":
ok = IsJSON(val.(string))
case "isSlice":
ok = IsSlice(val)
default:
// 3. call user custom validators, will call by reflect
ok = callValidatorValue(fm.fv, val, args)
Expand Down
1 change: 0 additions & 1 deletion validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,6 @@ func (v *Validation) GetWithDefault(key string) (val interface{}, exist, isDefau
// find default value
val, exist = v.defValues[key]
isDefault = exist

return
}

Expand Down

0 comments on commit 4dc93ac

Please sign in to comment.