mirror of
https://github.com/goccy/go-yaml.git
synced 2025-12-07 22:00:12 +00:00
Add decode option that allows specific field prefixes (#795)
This would be paired with DisallowUnknownField where you generally want to make sure the yaml does not have unknown fields, but allow for cases where the yaml has some extra stuff in it, e.g. for custom metadata or using fields as variables for anchors. In our specific case we allow `x-*` fields for these cases. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
parent
25e5d90942
commit
90e8525591
3 changed files with 46 additions and 1 deletions
12
decode.go
12
decode.go
|
|
@ -40,6 +40,7 @@ type Decoder struct {
|
|||
isResolvedReference bool
|
||||
validator StructValidator
|
||||
disallowUnknownField bool
|
||||
allowedFieldPrefixes []string
|
||||
allowDuplicateMapKey bool
|
||||
useOrderedMap bool
|
||||
useJSONUnmarshaler bool
|
||||
|
|
@ -1446,7 +1447,16 @@ func (d *Decoder) decodeStruct(ctx context.Context, dst reflect.Value, src ast.N
|
|||
// Unknown fields are expected (they could be fields from the parent struct).
|
||||
if len(unknownFields) != 0 && d.disallowUnknownField && src.GetToken() != nil {
|
||||
for key, node := range unknownFields {
|
||||
return errors.ErrUnknownField(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken())
|
||||
var ok bool
|
||||
for _, prefix := range d.allowedFieldPrefixes {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
return errors.ErrUnknownField(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1933,6 +1933,32 @@ children:
|
|||
t.Fatalf(`v.Children[1].B should be 2, got %d`, v.Children[1].B)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("with allowed prefixes", func(t *testing.T) {
|
||||
var v struct {
|
||||
A string `yaml:"a"`
|
||||
}
|
||||
yml := `---
|
||||
a: a_value
|
||||
x-some-extra-thing: b_value
|
||||
`
|
||||
|
||||
if err := yaml.NewDecoder(strings.NewReader(yml), yaml.DisallowUnknownField(), yaml.AllowFieldPrefixes("x-")).Decode(&v); err != nil {
|
||||
t.Fatalf(`parsing should succeed: %s`, err)
|
||||
}
|
||||
|
||||
yml = `---
|
||||
a: a_value
|
||||
b: b_value
|
||||
x-some-extra-thing: b_value
|
||||
`
|
||||
|
||||
err := yaml.NewDecoder(strings.NewReader(yml), yaml.DisallowUnknownField(), yaml.AllowFieldPrefixes("x-")).Decode(&v)
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestDecoder_AllowDuplicateMapKey(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,15 @@ func DisallowUnknownField() DecodeOption {
|
|||
}
|
||||
}
|
||||
|
||||
// AllowFieldPrefixes, when paired with [DisallowUnknownField], allows fields
|
||||
// with the specified prefixes to bypass the unknown field check.
|
||||
func AllowFieldPrefixes(prefixes ...string) DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
d.allowedFieldPrefixes = append(d.allowedFieldPrefixes, prefixes...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AllowDuplicateMapKey ignore syntax error when mapping keys that are duplicates.
|
||||
func AllowDuplicateMapKey() DecodeOption {
|
||||
return func(d *Decoder) error {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue