I am trying to parse a YAML file with Go. The problem is that the keys in the YAML file might not always be the same. This is to do API versioning so the user can define the
First, you are trying to parse the root as an Environment
, but its actual type is map[string]Environment
. Second, you are going to need a custom Unmarshaler if you want to keep that type structure. Something like this:
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)
}
Output (after using 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,
},
},
},
}