v9
When I attempt to use a custom validator on a struct key that is a pointer, it always seems to fail, without actually running the validator.
Cut down example:
type Foo struct {
Bar *string `json:"bar" validate:"fake"`
}
func FakeValidator(fl validator.FieldLevel) bool {
fmt.Println("FakeValidator run")
return true
}
func RegisterCustomValidators(validate *validator.Validate) {
validate.RegisterValidation("fake", FakeValidator)
}
When I run this, I get the following output:
INFO[0003] main.Foo{Bar:(*string)(nil)}
ERRO[0003] error: validation error error="Key: 'Foo.Bar' Error:Field validation for 'Bar' failed on the 'fake' tag"
Note that FakeValidator run is never output anywhere.
If I change the definition of my struct to remove the pointer:
type Foo struct {
Bar string `json:"bar" validate:"fake"`
}
Then I get the following (expected) output when I run:
INFO[0008] main.Foo{Bar:""}
FakeValidator run
I would expect that when I use my 'pointer' version, it should work the same way as the 'non-pointer version'. Basically I need to make my own version of the required tag as a custom validator.. but that determines whether it is required based on various rules. I had a look at the require code, and I don't see that it's any different to how I am approaching it, so can only assume that there is something 'higher up' that breaks it for my pointer version when using a custom validator.
Hey @0xdevalias I haven't had time to prove it but I think it's because it gets into this block when it's a pointer and nil, most use cases incorporate required and omitempty which is probably why this hasn't come up before.
I will look into correcting the logic this weekend to support your use case and thanks for bringing this to my attention.
Sounds good, thanks :)
Just wanted to add a little extra context here in case i'm likely to run into another issue from here. I think the basic flows I want to implement is going to be something like:
IF customValidatorRequired THEN required
IF NOT customValidatorRequired THEN omitempty ELSE otherCustomValidators
I'm guessing I could probably build it up with the AND/OR operators, but not 100% how I would fit the omitempty part into it.
@0xdevalias it's sounding like it's a more complex validation, usually, once it get's complex enough I recommend using a Struct Level validation, and that way you can do whatever you want and also combine with the built-in validations.
Still looking into what else I can do with the initial problem, I'm a bit under the weather this weekend so not sure I'm going to get to it.
Do you think that the Struct Level validation will work in your situation?
Oo.. I think I must have mentally skipped over those.. They definitely do sound like they would work for what I need. Will play around with them and see. Thanks :)
Edit: Struct Level validation seems to have done the trick perfectly. Made all of the struct keys pointers, did the 'flow' validation at the StructLevel, and then can do omitempty + specific field validations for the ones that need it.
@0xdevalias glad that helped! I will look into incorporating this type of functionality into the next version 馃槃
I see validator v9 has a new parameter for RegisterValidation called callValidationEvenIfNull. Should fix this issue if passing true, but I haven't tested it though:
https://godoc.org/gopkg.in/go-playground/validator.v9#Validate.RegisterValidation
Most helpful comment
I see validator v9 has a new parameter for RegisterValidation called
callValidationEvenIfNull. Should fix this issue if passing true, but I haven't tested it though:https://godoc.org/gopkg.in/go-playground/validator.v9#Validate.RegisterValidation