我试图用go来解析一个yaml文件.问题是yaml文件中的键可能并不总是相同.这是为了进行API版本控制,因此用户可以定义它们支持的版本.例如V1,V2,V3等.它们不需要按顺序排列,可以省略不支持IE V0,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) }
我在这里看到了一个类似的问题Golang parse a json with DYNAMIC key
这是在顶层,并没有完全弄清楚如何从结构内部做到这一点.
首先,您尝试将根解析为环境,但其实际类型是map [string] Environment.其次,如果要保留该类型结构,则需要自定义
原文链接:https://www.f2er.com/go/242050.htmlUnmarshaler
.像这样的东西:
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",SkipVersionValidation: true,SkipMimeTypeValidation: true,}