title: Dynamically parse yaml field to one of a finite set of structs in Go
body: <p>I have a <code>yaml</code> file, where one field could be represented by one of possible kinds of structs. To simplify the code and yaml files, let's say I have these yaml files:</p>
  <pre class="lang-yaml prettyprint-override"><code>kind: &quot;foo&quot;
  spec:
    fooVal: 4
  </code></pre>
  <pre class="lang-yaml prettyprint-override"><code>kind: &quot;bar&quot;
  spec:
    barVal: 5
  </code></pre>
  <p>And these structs for parsing:</p>
  <pre class="lang-golang prettyprint-override"><code>    type Spec struct {
          Kind string      `yaml:&quot;kind&quot;`
          Spec interface{} `yaml:&quot;spec&quot;`
      }
      type Foo struct {
          FooVal int `yaml:&quot;fooVal&quot;`
      }
      type Bar struct {
          BarVal int `yaml:&quot;barVal&quot;`
      }
  </code></pre>
  <p>I know that I can use <code>map[string]interface{}</code> as a type of <code>Spec</code> field. But the real example is more complex, and involves more possible struct types, not only <code>Foo</code> and <code>Bar</code>, this is why I don't like to parse <code>spec</code> into the field.</p>
  <p>I've found a workaround for this: unmarshal the yaml into intermediate struct, then check <code>kind</code> field, and marshal <code>map[string]interface{}</code> field into yaml back, and unmarshal it into concrete type:</p>
  <pre class="lang-golang prettyprint-override"><code>    var spec Spec
      if err := yaml.Unmarshal([]byte(src), &amp;spec); err != nil {
          panic(err)
      }
      tmp, _ := yaml.Marshal(spec.Spec)
      if spec.Kind == &quot;foo&quot; {
          var foo Foo
          yaml.Unmarshal(tmp, &amp;foo)
          fmt.Printf(&quot;foo value is %d\n&quot;, foo.FooVal)
      }
      if spec.Kind == &quot;bar&quot; {
          tmp, _ := yaml.Marshal(spec.Spec)
          var bar Bar
          yaml.Unmarshal(tmp, &amp;bar)
          fmt.Printf(&quot;bar value is %d\n&quot;, bar.BarVal)
      }
  </code></pre>
  <p>But it requires additional step and consumes more memory (real yaml file could be bigger than in examples). Does some more elegant way exist to unmarshal yaml dynamically into a finite set of structs?</p>
  <p>Update: I'm using <code>github.com/go-yaml/yaml v2.1.0</code> Yaml parser.</p>