Reputation: 4274
I'm trying to get simple YAML parsing in go working with gopkg.in/yaml.v2
.
From the documentation:
Maps and pointers (to a struct, string, int, etc) are accepted as out values. If an internal pointer within a struct is not initialized, the yaml package will initialize it if necessary for unmarshalling the provided data. The out parameter must not be nil.
The type of the decoded values should be compatible with the respective values in out. If one or more values cannot be decoded due to a type mismatches, decoding continues partially until the end of the YAML content, and a *yaml.TypeError is returned with details for all missed values.
Note the important bits here: "pointer within struct initialized if nec'y", and "yaml.TypeError returned if a value can't be decoded".
Now:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type YamlTypeA struct {
D string `yaml: "d"`
E string `yaml: "e"`
}
type YamlTypeB struct {
F string `yaml: "f"`
}
type YamlTypeC struct {
TypeA *YamlTypeA `yaml: "a"`
TypeB []YamlTypeB `yaml: "b"`
}
func main() {
var yamlObj YamlTypeC
text := []byte(`
---
a:
d: foo
e: bar
b: [{f: "fails"},
{f: "completely"}]
`)
err := yaml.Unmarshal(text,&yamlObj)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("OK")
fmt.Printf("TypeA.D: %s\n", yamlObj.TypeA.D)
fmt.Printf("I have %d TypeB\n", len(yamlObj.TypeB))
}
yields
OK
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x4014b3]
which appears to violate the promises made in the documentation jointly. If I make the nested YamlTypeA immediate instead of a pointer, the result is that the output value is not touched, still no error:
OK
TypeA.D:
I have 0 TypeB
What gives here? Is it just broken / poorly documented? How can you get nested struct values to parse out of YAML? (Using maps of maps is cumbersome and not at all a solution here.)
Upvotes: 2
Views: 1559
Reputation: 109397
You have spaces in your struct tags, so they're being ignored:
type YamlTypeA struct {
D string `yaml:"d"`
E string `yaml:"e"`
}
type YamlTypeB struct {
F string `yaml:"f"`
}
type YamlTypeC struct {
TypeA *YamlTypeA `yaml:"a"`
TypeB []YamlTypeB `yaml:"b"`
}
Upvotes: 5