From 866bd2a94660780004fd7b3063463260aefe7f89 Mon Sep 17 00:00:00 2001 From: Geoff Baskwill Date: Fri, 2 Feb 2018 16:39:49 -0500 Subject: [PATCH] Support translating field errors when field is of kind reflect.Ptr Previously, if fields were of kind `reflect.Ptr`, the translation of validation errors used the default string, resulting in unexpected output. Now the default translations use the field's `Elem()` kind (for example for `*string` the `Elem()` is `string`), resulting in much more natural output. --- translations/en/en.go | 56 +++++++++++++++++++++++++++++++++----- translations/en/en_test.go | 39 ++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/translations/en/en.go b/translations/en/en.go index a5454cc..551401f 100644 --- a/translations/en/en.go +++ b/translations/en/en.go @@ -69,6 +69,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var digits uint64 + var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) @@ -79,7 +80,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er goto END } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string @@ -154,6 +160,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var digits uint64 + var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) @@ -164,7 +171,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er goto END } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string @@ -239,6 +251,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var digits uint64 + var kind reflect.Kind if idx := strings.Index(fe.Param(), "."); idx != -1 { digits = uint64(len(fe.Param()[idx+1:])) @@ -249,7 +262,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er goto END } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string @@ -359,6 +377,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var f64 float64 var digits uint64 + var kind reflect.Kind fn := func() (err error) { @@ -371,7 +390,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er return } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string @@ -472,6 +496,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var f64 float64 var digits uint64 + var kind reflect.Kind fn := func() (err error) { @@ -484,7 +509,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er return } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string @@ -585,6 +615,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var f64 float64 var digits uint64 + var kind reflect.Kind fn := func() (err error) { @@ -597,7 +628,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er return } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string @@ -698,6 +734,7 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er var t string var f64 float64 var digits uint64 + var kind reflect.Kind fn := func() (err error) { @@ -710,7 +747,12 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er return } - switch fe.Kind() { + kind = fe.Kind() + if kind == reflect.Ptr { + kind = fe.Type().Elem().Kind() + } + + switch kind { case reflect.String: var c string diff --git a/translations/en/en_test.go b/translations/en/en_test.go index f5be5f6..93a4fef 100644 --- a/translations/en/en_test.go +++ b/translations/en/en_test.go @@ -129,6 +129,13 @@ func TestTranslations(t *testing.T) { UinxAddr string `validate:"unix_addr"` // can't fail from within Go's net package currently, but maybe in the future MAC string `validate:"mac"` IsColor string `validate:"iscolor"` + StrPtrMinLen *string `validate:"min=10"` + StrPtrMaxLen *string `validate:"max=1"` + StrPtrLen *string `validate:"len=2"` + StrPtrLt *string `validate:"lt=1"` + StrPtrLte *string `validate:"lte=1"` + StrPtrGt *string `validate:"gt=10"` + StrPtrGte *string `validate:"gte=10"` } var test Test @@ -171,6 +178,10 @@ func TestTranslations(t *testing.T) { test.MultiByte = "1234feerf" + s := "toolong" + test.StrPtrMaxLen = &s + test.StrPtrLen = &s + err = validate.Struct(test) NotEqual(t, err, nil) @@ -565,6 +576,34 @@ func TestTranslations(t *testing.T) { ns: "Test.RequiredMultiple", expected: "RequiredMultiple is a required field", }, + { + ns: "Test.StrPtrMinLen", + expected: "StrPtrMinLen must be at least 10 characters in length", + }, + { + ns: "Test.StrPtrMaxLen", + expected: "StrPtrMaxLen must be a maximum of 1 character in length", + }, + { + ns: "Test.StrPtrLen", + expected: "StrPtrLen must be 2 characters in length", + }, + { + ns: "Test.StrPtrLt", + expected: "StrPtrLt must be less than 1 character in length", + }, + { + ns: "Test.StrPtrLte", + expected: "StrPtrLte must be at maximum 1 character in length", + }, + { + ns: "Test.StrPtrGt", + expected: "StrPtrGt must be greater than 10 characters in length", + }, + { + ns: "Test.StrPtrGte", + expected: "StrPtrGte must be at least 10 characters in length", + }, } for _, tt := range tests {