Skip to content

Commit 9d0a7f2

Browse files
authored
fix validation error position for container type (#716)
1 parent 5d830d0 commit 9d0a7f2

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

‎decode.go‎

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1453,7 +1453,10 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N
14531453
node, exists := keyToNodeMap[structField.RenderName]
14541454
if exists {
14551455
// TODO: to make FieldError message cutomizable
1456-
return errors.ErrSyntax(fmt.Sprintf("%s", err), node.GetToken())
1456+
return errors.ErrSyntax(
1457+
fmt.Sprintf("%s", err),
1458+
d.getParentMapTokenIfExistsForValidationError(node.Type(), node.GetToken()),
1459+
)
14571460
} else if t := src.GetToken(); t != nil && t.Prev != nil && t.Prev.Prev != nil {
14581461
// A missing required field will not be in the keyToNodeMap
14591462
// the error needs to be associated with the parent of the source node
@@ -1467,6 +1470,37 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N
14671470
return nil
14681471
}
14691472

1473+
// getParentMapTokenIfExists if the NodeType is a container type such as MappingType or SequenceType,
1474+
// it is necessary to return the parent MapNode's colon token to represent the entire container.
1475+
func (d *Decoder) getParentMapTokenIfExistsForValidationError(typ ast.NodeType, tk *token.Token) *token.Token {
1476+
if tk == nil {
1477+
return nil
1478+
}
1479+
if typ == ast.MappingType {
1480+
// map:
1481+
// key: value
1482+
// ^ current token ( colon )
1483+
if tk.Prev == nil {
1484+
return tk
1485+
}
1486+
key := tk.Prev
1487+
if key.Prev == nil {
1488+
return tk
1489+
}
1490+
return key.Prev
1491+
}
1492+
if typ == ast.SequenceType {
1493+
// map:
1494+
// - value
1495+
// ^ current token ( sequence entry )
1496+
if tk.Prev == nil {
1497+
return tk
1498+
}
1499+
return tk.Prev
1500+
}
1501+
return tk
1502+
}
1503+
14701504
func (d *Decoder) decodeArray(ctx context.Context, dst reflect.Value, src ast.Node) error {
14711505
d.stepIn()
14721506
defer d.stepOut()

‎testdata/validate_test.go‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,37 @@ lt10: 20
174174
Inner `yaml:",inline"`
175175
}{},
176176
},
177+
{
178+
TestName: "Test map",
179+
YAMLContent: `
180+
map:
181+
hello: hello
182+
hello2: hello`,
183+
ExpectedErr: `[2:4] Key: 'Map' Error:Field validation for 'Map' failed on the 'eq' tag
184+
> 2 | map:
185+
^
186+
3 | hello: hello
187+
4 | hello2: hello`,
188+
Instance: &struct {
189+
// Make sure that this map is not set
190+
Map map[string]string `yaml:"map" validate:"eq=0"`
191+
}{},
192+
},
193+
{
194+
TestName: "Test sequence",
195+
YAMLContent: `
196+
map:
197+
- value
198+
`,
199+
ExpectedErr: `[2:4] Key: 'Map' Error:Field validation for 'Map' failed on the 'eq' tag
200+
> 2 | map:
201+
^
202+
3 | - value`,
203+
Instance: &struct {
204+
// Make sure that this map is not set
205+
Map []string `yaml:"map" validate:"eq=0"`
206+
}{},
207+
},
177208
}
178209

179210
for _, tc := range cases {

0 commit comments

Comments
 (0)