如何在 Golang 中使用动态键解析 YAML
Posted
技术标签:
【中文标题】如何在 Golang 中使用动态键解析 YAML【英文标题】:How to parse YAML with dynamic key in Golang 【发布时间】:2015-11-15 19:29:25 【问题描述】:我正在尝试使用 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)
我看到了similar question asked here
这是在顶层,我还没有完全弄清楚如何从结构内部做到这一点。
【问题讨论】:
【参考方案1】:首先,您尝试将根解析为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)
输出(使用makeup后):
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,
,
,
,
【讨论】:
哇,好人,谢谢。很酷,看看这是如何在 go 中完成的。有趣的是,有时您需要多少代码来解析 yaml!以上是关于如何在 Golang 中使用动态键解析 YAML的主要内容,如果未能解决你的问题,请参考以下文章