go-playground / validator

:100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
MIT License
16.72k stars 1.32k forks source link

Friendly error message for list validate #954

Open ccpwcn opened 2 years ago

ccpwcn commented 2 years ago

Package version eg. v9, v10:

v10 gin

Issue, Question or Enhancement:

I have a sub-struct, sub-struct is a list field of parent struct, show code:

type Parent struct {
    Name String `json:"name"`
    Children []Child `json:"children" validate:"min=1,dive"`
}
type Child struct {
    Name String `json:"name" validate:"max=10,min=1"`
    Address String `json:"address" validate:"max=10,min=1"`
}

when I post tow or more children elements, how can I fetch a friendly error message that which element is invalid? post json:

{
  "name": "father",
  "children": [
    {
      "name": "one",
      "address": "aaaaaaaaaaaaaaaaaaaaaaaaaaa"
    },
    {
      "name": "two",
      "address": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
    }
  ]
}

output message like:

Parent.Child[1].Address": "too long, the number of characters must less that 10"

expect message is: the first element of parent field named address is too long, the number of characters must less that 10, like that, the fourth children address is invalid(第四项的地址无效)

why require this? the message Parent.Child[1].Address": "too long, the number of characters must less that 10" is pretty user unfriendly. because, users does not understand computer, Child[1] is actually the second(we known, the index of list start with 0, but users does not known)

I try use custom function on Child'Address field, but cannot do it. example code:

type Child struct {
    Name String `json:"name" validate:"max=10,min=1"`
    Address String `json:"address" validate:"max=10,min=1,checkAddress"`
}

// Omit the registration validator code

var addressPattern = regexp.MustCompile(`^[a-zA-Z][a-z_A-Z0-9]*$`)
func CheckAddress(fl validator.FieldLevel) bool {
    if field, ok := fl.Field().Interface().(string); ok {
        return addressPattern.MatchString(field)
    } else {
        return false
    }
}

I got error message like "Parent.Children[1].Address": "Key: 'Parent.Children[1].Address' Error:Field validation for 'Address' failed on the 'checkAddress' tag"

I use custom error message:

err = v.RegisterTranslation("checkAddress", Trans, oT, translation)
// some other code
func oT(ut ut.Translator) (err error) {
    if err = ut.Add("checkAddress", "the field {0} format invalid, must start with 26 english letters", true); err != nil {
        return err
    }
    return nil
}
func translation(ut ut.Translator, fe validator.FieldError) (t string) {
    var err error
    if t, err = ut.T("checkAddress", fe.Field()); err == nil {
        return t
    }
    return "unknown error"
}

Then, I got error message like "Parent.Children[1].Address": "the field Address format invalid, must start with 26 english letters"

two questions:

  1. when parent has many children, the message cannot tell me which child's address is invalid
  2. use golang validator v10 in gin, frontent software project developmented by vue framework, some form field has label named address detail and it's json key is address(this scene, form has many addresses), friendly message is the fifth address detail is too long or the third address detail format is invalid, must start with 26 english letters.

How can I do it??? thanks any baby!!!

vuon9 commented 1 year ago

Having your own translation seems the best solution. This issue related to https://github.com/go-playground/validator/issues/524