Open
Description
What happened?
I'm facing an issue with validating a struct that contains a map field. The map's keys and values need to be validated, but the current setup isn't working as expected.
Struct Definitions
- I have a struct
Outer
with a fieldInner
that is a map of typemap[string]Inner
Outer.Inner
is of typeInner
and has a single fieldValue
type Inner struct {
Value string `validate:"max=5"`
}
type Outer struct {
Inner map[string]Inner `validate:"dive,keys,max=5,endkeys"`
}
Issue
- Current Behavior: Validation does not seem to apply to the map values (
Inner
structs) as expected. - Workarounds
a. Adding,required
afterendkeys
seems to trigger the validation, but it also prevents (with validator.WithRequiredStructEnabled()) empty struct values (Inner{}
), which is not the desired behavior.
b. Removing key validations and retaining onlydive
also triggers validation on values (but key validations are missed) - Documentation: I did not find any similar mention or examples in the documentation.
Is this a bug ? Or am I supposed to do something differently to achieve my desired behavior ?
Version
v10.26.0
Example Code
package main
import (
"fmt"
"github.com/go-playground/validator/v10"
)
type Inner struct {
Value string `validate:"max=5"`
}
type Outer1 struct {
Inner map[string]Inner `validate:"dive,keys,max=5,endkeys"`
}
type Outer2 struct {
Inner map[string]Inner `validate:"dive"`
}
type Outer3 struct {
Inner map[string]Inner `validate:"dive,keys,max=5,endkeys,required"`
}
func main() {
v := validator.New(validator.WithRequiredStructEnabled())
// Should fail, but passes
fmt.Println("Outer1:", v.Struct(Outer1{Inner: map[string]Inner{
"a": {Value: "1234567890"},
}}))
// Should fail, and fails (but there is no validation for keys)
fmt.Println("Outer2:", v.Struct(Outer2{Inner: map[string]Inner{
"a": {Value: "1234567890"},
}}))
// Should fail, and fails (but has extra required validation, which is not intended)
fmt.Println("Outer3:", v.Struct(Outer3{Inner: map[string]Inner{
"a": {Value: "1234567890"},
}}))
// Should fail (due to required), but I don't want it to fail
fmt.Println("Outer3 (a):", v.Struct(Outer3{Inner: map[string]Inner{
"a": {Value: ""},
}}))
}
// Actual output:
// Outer1: <nil>
// Outer2: Key: 'Outer2.Inner[a].Value' Error:Field validation for 'Value' failed on the 'max' tag
// Outer3: Key: 'Outer3.Inner[a].Value' Error:Field validation for 'Value' failed on the 'max' tag
// Outer3 (a): Key: 'Outer3.Inner[a]' Error:Field validation for 'Inner[a]' failed on the 'required' tag