From b517e3281eb71575e4c6063c108ebb45e95c0996 Mon Sep 17 00:00:00 2001 From: peerpackerhe Date: Thu, 24 Apr 2025 21:06:50 +0800 Subject: [PATCH 1/2] update .gitignore add .idea,.vscode --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6e43fac0d..aa95ed23b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ _testmain.go *.txt cover.html README.html +.idea +.vscode \ No newline at end of file From 7b40200144abf8cdc48af62c74ac28b9aa2373e4 Mon Sep 17 00:00:00 2001 From: peerpackerhe Date: Thu, 24 Apr 2025 21:42:28 +0800 Subject: [PATCH 2/2] add custom top reflect.Value in fieldError for custom msg support a entry --- errors.go | 15 +++++++++++++++ struct_level.go | 2 ++ validator.go | 6 ++++++ validator_test.go | 6 +++++- 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/errors.go b/errors.go index 9a1b1abe9..04f1d9d69 100644 --- a/errors.go +++ b/errors.go @@ -160,8 +160,16 @@ type FieldError interface { Error() string } +type TopFieldError interface { + FieldError + + // Top returns the actual field's parent value in case needed for creating custom the error + Top() reflect.Value +} + // compile time interface checks var _ FieldError = new(fieldError) +var _ TopFieldError = new(fieldError) var _ error = new(fieldError) // fieldError contains a single field's validation error along @@ -179,6 +187,7 @@ type fieldError struct { param string kind reflect.Kind typ reflect.Type + top reflect.Value } // Tag returns the validation tag that failed. @@ -273,3 +282,9 @@ func (fe *fieldError) Translate(ut ut.Translator) string { return fn(ut, fe) } + +// Top returns the actual field's parent value in case needed for creating custom the error +// message +func (fe *fieldError) Top() reflect.Value { + return fe.top +} diff --git a/struct_level.go b/struct_level.go index c0d89cfbe..9ffb6cfff 100644 --- a/struct_level.go +++ b/struct_level.go @@ -135,6 +135,7 @@ func (v *validate) ReportError(field interface{}, fieldName, structFieldName, ta structfieldLen: uint8(len(structFieldName)), param: param, kind: kind, + top: v.top, }, ) return @@ -153,6 +154,7 @@ func (v *validate) ReportError(field interface{}, fieldName, structFieldName, ta param: param, kind: kind, typ: fv.Type(), + top: v.top, }, ) } diff --git a/validator.go b/validator.go index 80da095a6..205275360 100644 --- a/validator.go +++ b/validator.go @@ -129,6 +129,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr structfieldLen: uint8(len(cf.name)), param: ct.param, kind: kind, + top: v.top, }, ) return @@ -154,6 +155,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr param: ct.param, kind: kind, typ: current.Type(), + top: v.top, }, ) return @@ -199,6 +201,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr param: ct.param, kind: kind, typ: typ, + top: v.top, }, ) return @@ -413,6 +416,7 @@ OUTER: param: ct.param, kind: kind, typ: typ, + top: v.top, }, ) @@ -433,6 +437,7 @@ OUTER: param: ct.param, kind: kind, typ: typ, + top: v.top, }, ) } @@ -474,6 +479,7 @@ OUTER: param: ct.param, kind: kind, typ: typ, + top: v.top, }, ) diff --git a/validator_test.go b/validator_test.go index 7e314d609..1eb41bbe9 100644 --- a/validator_test.go +++ b/validator_test.go @@ -351,7 +351,7 @@ func TestStructLevelInvalidError(t *testing.T) { validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{}) var test StructLevelInvalidErr - + val := reflect.ValueOf(test) err := validate.Struct(test) NotEqual(t, err, nil) @@ -367,6 +367,10 @@ func TestStructLevelInvalidError(t *testing.T) { Equal(t, fe.ActualTag(), "required") Equal(t, fe.Kind(), reflect.Invalid) Equal(t, fe.Type(), reflect.TypeOf(nil)) + top, ok := fe.(TopFieldError) + Equal(t, ok, true) + Equal(t, top.Top().Kind(), val.Kind()) + Equal(t, top.Top().Type().Name(), val.Type().Name()) } func TestNameNamespace(t *testing.T) {