diff --git a/baked_in.go b/baked_in.go index b6fbaafa..1eac7925 100644 --- a/baked_in.go +++ b/baked_in.go @@ -1904,12 +1904,19 @@ func excludedUnless(fl FieldLevel) bool { if len(params)%2 != 0 { panic(fmt.Sprintf("Bad param number for excluded_unless %s", fl.FieldName())) } + var canBeFilled bool for i := 0; i < len(params); i += 2 { - if !requireCheckFieldValue(fl, params[i], params[i+1], false) { - return !hasValue(fl) + if requireCheckFieldValue(fl, params[i], params[i+1], false) { + canBeFilled = true + break } } - return true + + if canBeFilled { + return true + } + + return !hasValue(fl) } // excludedWith is the validation function diff --git a/validator_test.go b/validator_test.go index 0f96b777..bd7ee481 100644 --- a/validator_test.go +++ b/validator_test.go @@ -11140,6 +11140,24 @@ func TestRequiredUnless(t *testing.T) { Inner: &Inner{Field: &fieldVal}, } _ = validate.Struct(test3) + + test4 := struct { + Field1 int + Field2 string `validate:"required_unless: Field1 1 Field1 2"` + Field3 int + Field4 string `validate:"required_unless: Field3 1 Field3 2"` + }{ + Field1: 1, + Field3: 3, + } + + errs = validate.Struct(test4) + NotEqual(t, errs, nil) + + ve = errs.(ValidationErrors) + Equal(t, len(ve), 1) + + AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_unless") } func TestSkipUnless(t *testing.T) { @@ -12126,6 +12144,26 @@ func TestExcludedUnless(t *testing.T) { Inner: &Inner{Field: &fieldVal}, } _ = validate.Struct(panicTest) + + test9 := struct { + Field1 int + Field2 string `validate:"excluded_unless: Field1 1 Field1 2"` + Field3 int + Field4 string `validate:"excluded_unless: Field3 1 Field3 2"` + }{ + Field1: 1, + Field2: "foo", + Field3: 3, + Field4: "foo", + } + + errs = validate.Struct(test9) + NotEqual(t, errs, nil) + + ve = errs.(ValidationErrors) + Equal(t, len(ve), 1) + + AssertError(t, errs, "Field2", "Field2", "Field2", "Field2", "required_unless") } func TestLookup(t *testing.T) {