Validator: Get json tag value

Created on 31 Oct 2016  路  5Comments  路  Source: go-playground/validator

Package version eg. v8, v9:

v9

Issue, Question or Enhancement:

Hello!
My situation: I have pointer to struct with type interface{} and I validate it with the help of validator (v9). Validation works perfectly! But after getting array of validation errors (ValidationErrors) I'd like to get json tag value, not actual field name. For example:
I have such struct:
type Qwe struct {
Name string json:"name" validate:"required"
}
After validation I would like to get error message with json tag value "name", not "Name" (with a capital letter).

In the source code of validator I see a method Field() in interface FieldError with such comment:
" // returns the fields name with the tag name taking precedence over the
// fields actual name.
//
// eq. JSON name "fname"
// see ActualField for comparison"
But I don't see ActualField and don't get field name with the tag name taking precedence over the fields actual name.
Could you please help me with this problem?

Most helpful comment

@dkostenko here is some sample code:

validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
    name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]

    if name == "-" {
        return ""
    }

    return name
})

// ... validate

validationErrors := err.(validator.ValidationErrors)
validationErr := validationErrors[0]
fieldName := validationErr.Field() // this will return the JSON tag name

All 5 comments

I got it

validationErrors := err.(validator.ValidationErrors)
validationErr := validationErrors[0]
fieldName := validationErr.Field()
field, ok := reflect.TypeOf(args).Elem().FieldByName(fieldName)
fieldJSONName, _ := field.Tag.Lookup("json")

Sorry for disturbing

Hey @dkostenko no problem, but there is actually a better way built in to get any tag name, even JSON
you just have to register your own TagNameFunc and then essentially do the same thing you did to grab the tag name and return, the benefits to using the built in way is that the information is cached and function really only called once.

Then the err.Field() will have whatever name you returned from the function and err.StructField() will have the struct field name.

Sorry answering from my phone, I'll post some sample code once at a computer, but it's pretty easy to figure out :)

@dkostenko here is some sample code:

validate := New()
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
    name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]

    if name == "-" {
        return ""
    }

    return name
})

// ... validate

validationErrors := err.(validator.ValidationErrors)
validationErr := validationErrors[0]
fieldName := validationErr.Field() // this will return the JSON tag name

@deankarn Given that your solution above still works with v9, is there shorter/new/etc. way in v9? Just asking as it has been 3 years. Thanks!

For anyone using Gin and wanting to register this validator, there is an example here:

https://github.com/go-playground/validator/blob/v9/_examples/gin-upgrading-overriding/v8_to_v9.go

Was this page helpful?
0 / 5 - 0 ratings