Home > Backend Development > Golang > How to Dynamically Parse YAML Fields into a Finite Set of Structs in Go?

How to Dynamically Parse YAML Fields into a Finite Set of Structs in Go?

Mary-Kate Olsen
Release: 2024-10-29 09:49:02
Original
960 people have browsed it

How to Dynamically Parse YAML Fields into a Finite Set of Structs in Go?

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>
Copy after login
<code class="yaml">kind: "bar"
spec:
  barVal: 5</code>
Copy after login

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>
Copy after login

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>
Copy after login

And modify the Spec struct to use it:

<code class="go">type Spec struct {
    Kind string      `yaml:"kind"`
    Spec interface{} `yaml:"-" json:"-"`
}</code>
Copy after login

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>
Copy after login

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!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template