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
答案 0 :(得分:2)
之前已经以各种方式回答了这个问题,但是很长一段时间以来很容易将其拆分成界面然后处理这两种情况
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)
}
}
答案 1 :(得分:0)
这只是出色的@Benjamin Kadish answer above的后续版本,但这是一个更完整的版本,它使用yaml.v3,这使其更加明显。请注意,在Yaml v3中,未编组项目的类型为map[string]interface{}
,而不是map[interface{}]interface{}
。
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)
}
}
}
答案 2 :(得分:-1)
因为,go是静态类型语言,如果将val3
转换为已定义的结构,则不能只保留val3: ""
列表项。它应该是关键值对。例如。 (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)
}
)(如果你想要它是空的。)
这是修改后的代码
2018/02/02 01:07:36 {Entry:[map[keya1:val1 keya2:val2] map[keyb2:val2 keyb1:val1] map[val3:]]}
输出:
{{1}}