validator icon indicating copy to clipboard operation
validator copied to clipboard

Custom validators for struct fields

Open quentinmit opened this issue 4 years ago • 5 comments

  • [x] I have looked at the documentation here first?
  • [x] I have looked at the examples provided that may showcase my question here?

Package version eg. v9, v10:

v10

Issue, Question or Enhancement:

The documentation says that only required and omitempty can be used on struct-type fields. This makes some sense (most of the validators don't make sense on a struct, e.g. gt, alpha, etc.). However, it looks like custom validators don't get run, and they're treated as if they were required instead.

Code sample, to showcase or reproduce:

https://play.golang.org/p/ydSUIxEIE1k

package main

import (
	"log"

	"github.com/go-playground/validator/v10"
)

// User contains user information
type User struct {
	FirstName string `validate:"required"`
	LastName  string `validate:"required"`
	Mother    *User  `validate:"same-last-name"`
}

func main() {
	validate := validator.New()
	validate.RegisterValidation("same-last-name", func(fl validator.FieldLevel) bool {
		log.Printf("validation called on %s", fl.StructFieldName())
		return true
	})

	user := &User{
		FirstName: "Badger",
		LastName:  "Smith",
		Mother: &User{
			FirstName: "Jane",
			LastName:  "Imposter",
		},
	}
	log.Printf("validation results: %v", validate.Struct(user))
}

I expect this to log validation called on Mother and then successful validation; instead the validation fails (due to the nested User having a nil Mother) without the log message ever getting printed:

2009/11/10 23:00:00 validation results: Key: 'User.Mother.Mother' Error:Field validation for 'Mother' failed on the 'same-last-name' tag

Program exited.

If the structure is not recursive, the validation instead silently passes (again without actually calling the custom validator):

https://play.golang.org/p/XMirPpgbNFX

so this makes me think that the validator is being treated as if it were required.

I understand that it's possible to register a struct-level validator, but that's per-type and therefore can't be applied in cases like this where they need to be enabled for particular fields or with parameters.

quentinmit avatar Aug 11 '21 20:08 quentinmit

hey, there, maybe you can try this against v10:

	validate.RegisterValidation("same-last-name", func(fl validator.FieldLevel) bool {
		log.Printf("validation called on %s", fl.StructFieldName())
		return true
	}, true)

It works for me.

➜  go run main.go
2021/09/03 20:00:25 validation called on Mother
2021/09/03 20:00:25 validation results: <nil>

As you can see the function signature, it has already be supported.

codershangfeng avatar Sep 03 '21 12:09 codershangfeng

@quentinmit , have you solved your issue ?

petitout avatar Jan 30 '23 19:01 petitout

Just ran into this issue while trying to add validation to a struct containing a shopspring/decimal.

I registered a custom field validator and expected that it would get called for the decimal field, where I could cast field.Interface(), forcibly cast it to the decimal, and perform my custom validation logic there.

Tested on v10.12.0.

RayzorFlash avatar Apr 13 '23 19:04 RayzorFlash

Just ran into this issue while trying to add validation to a struct containing a shopspring/decimal.

I registered a custom field validator and expected that it would get called for the decimal field, where I could cast field.Interface(), forcibly cast it to the decimal, and perform my custom validation logic there.

Tested on v10.12.0.

Can you give an example of how you registered a custom field validator please?

lcucurachi avatar Aug 02 '23 16:08 lcucurachi

I am facing similar problem. @quentinmit Did you get it working?

ranahemantkumar avatar Oct 19 '23 12:10 ranahemantkumar