I am using go-playground/validator/v10
to validate some input and have some trouble with custom validation tags and functions. The problem is that the function is not called when one of the struct fields is a different struct. This is an example:
type ChildStruct struct {
Value int
}
type ParentStruct struct {
Child ChildStruct `validate:"myValidate"`
}
func myValidate(fl validator.FieldLevel) bool {
fmt.Println("INSIDE MY VALIDATOR") // <- This is never printed
return false
}
func main() {
validator := validator.New()
validator.RegisterValidation("myValidate", myValidate)
data := &ParentStruct{
Child: ChildStruct{
Value: 10,
},
}
validateErr := validator.Struct(data)
if validateErr != nil { // <- This is always nil since MyValidate is never called
fmt.Println("GOT ERROR")
fmt.Println(validateErr)
}
fmt.Println("DONE")
}
If I change the parentStruct to:
type ParentStruct struct {
Child int `validate:"myValidate"`
}
everything works.
If I add the validate:"myValidate"
part to the ChildStruct it is also working, however, then the error that is returned is saying that the ChildStruct.Value is wrong when it should say that the ParentStruct.Child is wrong.
Anyone know what I am doing wrong?
After searching for a while I finally found a function called RegisterCustomTypeFunc
which registers a custom type which will make it possible for go-playground/validator/v10
to validate it. So the solution is to add the following to the example in the question:
func childStructCustomTypeFunc(field reflect.Value) interface{} {
if value, ok := field.Interface().(ChildStruct); ok {
return value.Value
}
return nil
}
Together with:
validator.RegisterCustomTypeFunc(childStructCustomTypeFunc, ChildStruct{})
Now the validator will go into the myValidate
function and the return message will be an error for the ParentStruct.Child
field