Dynamically Parsing YAML Fields to a Finite Set of Structs in Go
Parsing YAML files is a common task in many applications. However, sometimes a YAML file can contain fields that need to be represented by different types of structs. This can lead to complex code and cluttered YAML files.
For example, consider the following YAML files:
kind: "foo"
spec:
fooVal: 4
kind: "bar"
spec:
barVal: 5
And the corresponding structs for parsing:
type Spec struct {
Kind string `yaml:"kind"`
Spec interface{} `yaml:"spec"`
}
type Foo struct {
FooVal int `yaml:"fooVal"`
}
type Bar struct {
BarVal int `yaml:"barVal"`
}
One approach is to use a map[string]interface{} as the type for the Spec field. However, this approach can lead to additional complexity and memory consumption, especially for large YAML files.
A more elegant solution is to use the yamlNode struct:
type yamlNode struct {
unmarshal func(interface{}) error
}
func (n *yamlNode) UnmarshalYAML(unmarshal func(interface{}) error) error {
n.unmarshal = unmarshal
return nil
}
And modify the Spec struct to use it:
type Spec struct {
Kind string `yaml:"kind"`
Spec interface{} `yaml:"-" json:"-"`
}
With these changes, the UnmarshalYAML function for Spec can dynamically parse and unmarshal the Spec field into a specific struct type:
func (s *Spec) UnmarshalYAML(unmarshal func(interface{}) error) error {
type S Spec
type T struct {
S `yaml:",inline"`
Spec yamlNode `yaml:"spec"`
}
obj := &T{}
if err := unmarshal(obj); err != nil {
return err
}
*s = Spec(obj.S)
switch s.Kind {
case "foo":
s.Spec = new(Foo)
case "bar":
s.Spec = new(Bar)
default:
panic("kind unknown")
}
return obj.Spec.unmarshal(s.Spec)
}
This approach provides a more elegant and efficient solution for dynamically parsing YAML fields into a finite set of structs, making your code and YAML files much cleaner and easier to manage.
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3