[英]How to parse YAML with dynamic key in Golang
我试图用Go解析YAML文件。 问题是YAML文件中的键可能并不总是相同。 这是为了进行API版本控制,因此用户可以定义它们支持的版本。 例如V1,V2,V3等。它们不需要按顺序排列,可以省略它们不支持的版本,即V0,V2,V5等。
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
var data = `
---
development:
skip-header-validation: true
V1:
current: "1.0.0"
mime_types:
- application/vnd.company.jk.identity+json;
- application/vnd.company.jk.user+json;
- application/vnd.company.jk.role+json;
- application/vnd.company.jk.scope+json;
- application/vnd.company.jk.test+json;
skip-mime-type-validation: true
skip-version-validation: true
V2:
current: "2.0.0"
mime_types:
- application/vnd.company.jk.identity+json;
- application/vnd.company.jk.user+json;
- application/vnd.company.jk.role+json;
- application/vnd.company.jk.scope+json;
- application/vnd.company.jk.test+json;
`
type MajorVersion struct {
Current string `yaml:"current"`
MimeTypes []string `yaml:"mime_types"`
SkipVersionValidation bool `yaml:"skip-version-validation"`
SkipMimeTypeValidation bool `yaml:"skip-mime-type-validation"`
}
type Environment struct {
SkipHeaderValidation bool `yaml:"skip-header-validation"`
Version map[string]MajorVersion
}
func main() {
e := Environment{}
yaml.Unmarshal([]byte(data), &e)
fmt.Println(e)
}
这是在顶级,我还没有弄清楚如何从结构内部做到这一点。
首先,您尝试将根解析为Environment
,但其实际类型是map[string]Environment
。 其次,如果要保留该类型结构,则需要自定义Unmarshaler
。 像这样的东西:
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
var data = `
---
development:
skip-header-validation: true
V1:
current: "1.0.0"
mime_types:
- application/vnd.company.jk.identity+json;
- application/vnd.company.jk.user+json;
- application/vnd.company.jk.role+json;
- application/vnd.company.jk.scope+json;
- application/vnd.company.jk.test+json;
skip-mime-type-validation: true
skip-version-validation: true
V2:
current: "2.0.0"
mime_types:
- application/vnd.company.jk.identity+json;
- application/vnd.company.jk.user+json;
- application/vnd.company.jk.role+json;
- application/vnd.company.jk.scope+json;
- application/vnd.company.jk.test+json;
`
type MajorVersion struct {
Current string `yaml:"current"`
MimeTypes []string `yaml:"mime_types"`
SkipVersionValidation bool `yaml:"skip-version-validation"`
SkipMimeTypeValidation bool `yaml:"skip-mime-type-validation"`
}
type Environment struct {
SkipHeaderValidation bool
Versions map[string]MajorVersion
}
func (e *Environment) UnmarshalYAML(unmarshal func(interface{}) error) error {
var params struct {
SkipHeaderValidation bool `yaml:"skip-header-validation"`
}
if err := unmarshal(¶ms); err != nil {
return err
}
var versions map[string]MajorVersion
if err := unmarshal(&versions); err != nil {
// Here we expect an error because a boolean cannot be converted to a
// a MajorVersion
if _, ok := err.(*yaml.TypeError); !ok {
return err
}
}
e.SkipHeaderValidation = params.SkipHeaderValidation
e.Versions = versions
return nil
}
func main() {
var e map[string]Environment
if err := yaml.Unmarshal([]byte(data), &e); err != nil {
fmt.Println(err.Error())
}
fmt.Printf("%#v\n", e)
}
输出(使用化妆后 ):
map[string]main.Environment{
"development": {
SkipHeaderValidation: true,
Versions: {
"V2": {
Current: "2.0.0",
MimeTypes: {"application/vnd.company.jk.identity+json;", "application/vnd.company.jk.user+json;", "application/vnd.company.jk.role+json;", "application/vnd.company.jk.scope+json;", "application/vnd.company.jk.test+json;"},
SkipVersionValidation: false,
SkipMimeTypeValidation: false,
},
"V1": {
Current: "1.0.0",
MimeTypes: {"application/vnd.company.jk.identity+json;", "application/vnd.company.jk.user+json;", "application/vnd.company.jk.role+json;", "application/vnd.company.jk.scope+json;", "application/vnd.company.jk.test+json;"},
SkipVersionValidation: true,
SkipMimeTypeValidation: true,
},
},
},
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.