I'm trying to unmarshal YAML entries that can be either a string or a list of key: value strings (a map as per Go). I cannot figure out how to get this done sadly. I know I can write my own unmarshaller but that seems to only work with structs.
I have the first part working:
package main
import (
"log"
"gopkg.in/yaml.v2"
)
type Data struct {
Entry []Entry `yaml:"entries"`
}
type Entry map[string]string
var dat string = `
entries:
- keya1: val1
keya2: val2
- keyb1: val1
keyb2: val2
- val3`
func main() {
out := Data{}
if err := yaml.Unmarshal([]byte(dat), &out); err != nil {
log.Fatal(err)
}
log.Printf("%+v", out)
}
But the - val3
entry causes an error now, obviously. How can I get it to recognise both lists and single string entries?
Thank you
This has been answered in various ways before, but long story short it is easy unmarshall into an interface and then deal with both cases
type Entry interface{}
for _, entry := range out.Entry {
switch i := entry.(type) {
case string:
log.Printf("i is a string %+v\n", i)
case map[interface{}]interface{}:
log.Printf("i is a map %+v\n", i)
}
}
This is just a followup to the excellent @Benjamin Kadish answer above, but here's a somewhat more complete version and this uses yaml.v3, which makes it just a bit more obvious. Note that the type of the unmarshalled items is map[string]interface{}
instead of map[interface{}]interface{}
in yaml v3.
package main
import (
"gopkg.in/yaml.v3"
"log"
)
type Data struct {
Entry []Entry `yaml:"entries"`
}
type Entry interface {}
var dat string = `
entries:
- keya1: val1
keya2: val2
- keyb1: val1
keyb2: val2
- val3`
func main() {
out := Data{}
if err := yaml.Unmarshal([]byte(dat), &out); err != nil {
log.Fatal(err)
}
for _, entry := range out.Entry {
switch i := entry.(type) {
case string:
log.Printf("i is a string: %+v\n", i)
case map[string]interface{}:
log.Printf("i is a map.")
for k,v := range i {
log.Printf("%s=%v\n",k,v)
}
default:
log.Printf("Type i=%s", i)
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With