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:
<code class="yaml">kind: "foo" spec: fooVal: 4</code>
<code class="yaml">kind: "bar" spec: barVal: 5</code>
And the corresponding structs for parsing:
<code class="go">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"` }</code>
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:
<code class="go">type yamlNode struct { unmarshal func(interface{}) error } func (n *yamlNode) UnmarshalYAML(unmarshal func(interface{}) error) error { n.unmarshal = unmarshal return nil }</code>
And modify the Spec struct to use it:
<code class="go">type Spec struct { Kind string `yaml:"kind"` Spec interface{} `yaml:"-" json:"-"` }</code>
With these changes, the UnmarshalYAML function for Spec can dynamically parse and unmarshal the Spec field into a specific struct type:
<code class="go">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) }</code>
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.
The above is the detailed content of How to Dynamically Parse YAML Fields into a Finite Set of Structs in Go?. For more information, please follow other related articles on the PHP Chinese website!