【发布时间】:2021-03-19 14:24:54
【问题描述】:
我有一个yaml 文件,其中一个字段可以由一种可能的结构表示。为了简化代码和 yaml 文件,假设我有这些 yaml 文件:
kind: "foo"
spec:
fooVal: 4
kind: "bar"
spec:
barVal: 5
还有这些用于解析的结构体:
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"`
}
我知道我可以将map[string]interface{} 用作Spec 字段的一种类型。但是实际的例子更复杂,涉及到更多可能的结构类型,不仅仅是Foo和Bar,这就是为什么我不喜欢将spec解析到字段中。
我找到了一个解决方法:将 yaml 解组为中间结构,然后检查 kind 字段,并将 map[string]interface{} 字段编组到 yaml 中,并将其解组为具体类型:
var spec Spec
if err := yaml.Unmarshal([]byte(src), &spec); err != nil {
panic(err)
}
tmp, _ := yaml.Marshal(spec.Spec)
if spec.Kind == "foo" {
var foo Foo
yaml.Unmarshal(tmp, &foo)
fmt.Printf("foo value is %d\n", foo.FooVal)
}
if spec.Kind == "bar" {
tmp, _ := yaml.Marshal(spec.Spec)
var bar Bar
yaml.Unmarshal(tmp, &bar)
fmt.Printf("bar value is %d\n", bar.BarVal)
}
但它需要额外的步骤并消耗更多的内存(真正的 yaml 文件可能比示例中的大)。是否存在一些更优雅的方式来将 yaml 动态解组为一组有限的结构?
更新:我正在使用github.com/go-yaml/yaml v2.1.0 Yaml 解析器。
【问题讨论】:
-
你使用的是哪个 yaml 包和包的版本?
-
@mkopriva 抱歉,更新了问题
标签: parsing go yaml marshalling unmarshalling