Skip to content

Commit

Permalink
consider 'unknown field' errors to be strict errors
Browse files Browse the repository at this point in the history
Signed-off-by: Inteon <[email protected]>
  • Loading branch information
inteon committed Oct 31, 2021
1 parent b61fe18 commit baaeb5d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 17 deletions.
13 changes: 8 additions & 5 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,10 @@ func (p *parser) mapping() *Node {
// Decoder, unmarshals a node into a provided value.

type decoder struct {
doc *Node
aliases map[*Node]bool
terrors []string
doc *Node
aliases map[*Node]bool
terrors []string
strictErrors []string

stringMapType reflect.Type
generalMapType reflect.Type
Expand Down Expand Up @@ -361,6 +362,7 @@ func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
err := u.UnmarshalYAML(n)
if e, ok := err.(*TypeError); ok {
d.terrors = append(d.terrors, e.Errors...)
d.strictErrors = append(d.strictErrors, e.StrictErrors...)
return false
}
if err != nil {
Expand All @@ -377,12 +379,13 @@ func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good
if len(d.terrors) > terrlen {
issues := d.terrors[terrlen:]
d.terrors = d.terrors[:terrlen]
return &TypeError{issues}
return &TypeError{issues, nil}
}
return nil
})
if e, ok := err.(*TypeError); ok {
d.terrors = append(d.terrors, e.Errors...)
d.strictErrors = append(d.strictErrors, e.StrictErrors...)
return false
}
if err != nil {
Expand Down Expand Up @@ -908,7 +911,7 @@ func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
d.unmarshal(n.Content[i+1], value)
inlineMap.SetMapIndex(name, value)
} else if d.knownFields {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
d.strictErrors = append(d.strictErrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
}
}
return true
Expand Down
12 changes: 8 additions & 4 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1110,8 +1110,8 @@ func (s *S) TestUnmarshalerWholeDocument(c *C) {
}

func (s *S) TestUnmarshalerTypeError(c *C) {
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}, nil}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}, nil}
defer func() {
delete(unmarshalerResult, 2)
delete(unmarshalerResult, 4)
Expand Down Expand Up @@ -1141,8 +1141,8 @@ func (s *S) TestUnmarshalerTypeError(c *C) {
}

func (s *S) TestObsoleteUnmarshalerTypeError(c *C) {
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}, nil}
unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}, nil}
defer func() {
delete(unmarshalerResult, 2)
delete(unmarshalerResult, 4)
Expand Down Expand Up @@ -1605,6 +1605,10 @@ func (s *S) TestUnmarshalKnownFields(c *C) {
dec.KnownFields(item.known)
err := dec.Decode(value.Interface())
c.Assert(err, ErrorMatches, item.error)
if !item.unique {
// If a strict error occurs, the decoding should still be successful
c.Assert(value.Elem().Interface(), DeepEquals, item.value)
}
}
}

Expand Down
17 changes: 9 additions & 8 deletions yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ func (dec *Decoder) Decode(v interface{}) (err error) {
out = out.Elem()
}
d.unmarshal(node, out)
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
if len(d.terrors) > 0 || len(d.strictErrors) > 0 {
return &TypeError{d.terrors, d.strictErrors}
}
return nil
}
Expand All @@ -147,8 +147,8 @@ func (n *Node) Decode(v interface{}) (err error) {
out = out.Elem()
}
d.unmarshal(n, out)
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
if len(d.terrors) > 0 || len(d.strictErrors) > 0 {
return &TypeError{d.terrors, d.strictErrors}
}
return nil
}
Expand All @@ -166,8 +166,8 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
}
d.unmarshal(node, v)
}
if len(d.terrors) > 0 {
return &TypeError{d.terrors}
if len(d.terrors) > 0 || len(d.strictErrors) > 0 {
return &TypeError{d.terrors, d.strictErrors}
}
return nil
}
Expand Down Expand Up @@ -313,11 +313,12 @@ func failf(format string, args ...interface{}) {
// types. When this error is returned, the value is still
// unmarshaled partially.
type TypeError struct {
Errors []string
Errors []string
StrictErrors []string
}

func (e *TypeError) Error() string {
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(e.Errors, "\n "))
return fmt.Sprintf("yaml: unmarshal errors:\n %s", strings.Join(append(e.Errors, e.StrictErrors...), "\n "))
}

type Kind uint32
Expand Down

0 comments on commit baaeb5d

Please sign in to comment.