I've been trying to write a custom UnmarshalYAML
function that will unmarshal a yaml to a struct and also keep unexpected parameters saving them into a map into the struct itself.
I've tried writing this (https://go.dev/play/p/azf2hksriQ1) but, of course, I get an infinite loop when I try to unmarshal the struct inside the UnmarshalYAML
.
Does anyone have any suggestion on how to make this work? Thank you very much!
You can use a simple wrapping technique where you define a type alias for your original type (so yaml.Unmarshaler
won't call your UmarshalYAML
method) and create a struct which embeds all known and unknown parameters.
type Foo struct {
Param1 string `yaml:"param1"`
Param2 []int `yaml:"param2"`
// NOTE: we explicitly ignore this parameter so it won't be
// eventually unmarshaled
Extensions map[string]any `yaml:"-"`
}
// UnmarshalYAML implements the yaml.UnmarshalYAML interface.
func (f *Foo) UnmarshalYAML(value *yaml.Node) error {
// Here we are wrapping Foo, so it will be unmarshaled
// using without calling foo.UnmarshalYAML
type Wrapped Foo
// NOTE: for yaml it's required to provide inline
// option if we would like to embed
var val struct {
Wrapped `yaml:",inline"`
Extensions map[string]any `yaml:",inline"`
}
if err := value.Decode(&val); err != nil {
return err
}
*f = Foo(val.Wrapped)
f.Extensions = val.Extensions
return nil
}