Here is a list of YAML parsers for Go programming language. For each one, I will provide a short description, an evaluation and an example source code.
You can download an archive with example source code here.
Note that names of the parsers were customized by myslef as they are almost all named goyaml :o)
In the code example, we will parse following YAML file:
foo: 1
bar:
- one
- two
In each source, we will extract and print the first element of the list in foo key of the map at the root of the document.
This parser is very handy to manage configuration files. You declare a struct that maps the structure of the YAML configuration file and you pass a reference to this struct to the parser while loading configuration file. This parser will populate struct with data in the file.
This parser is probably the best way to manage YAML configuration files.
package main
import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
"os"
)
type Config struct {
Foo string
Bar []string
}
func main() {
filename := os.Args[1]
var config Config
source, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
err = yaml.Unmarshal(source, &config)
if err != nil {
panic(err)
}
fmt.Printf("Value: %#v\n", config.Bar[0])
}
To run this sample code, type following command:
go run src/goyaml.go src/test.yml
This is a low level parser, which means that a file will result in a nodes tree that you will have to explore by hand (as in the example that follows):
package main
import (
"fmt"
"github.com/kylelemons/go-gypsy/yaml"
"os"
)
func nodeToMap(node yaml.Node) (yaml.Map) {
m, ok := node.(yaml.Map)
if !ok {
panic(fmt.Sprintf("%v is not of type map", node))
}
return m
}
func nodeToList(node yaml.Node) (yaml.List) {
m, ok := node.(yaml.List)
if !ok {
panic(fmt.Sprintf("%v is not of type list", node))
}
return m
}
func main() {
filename := os.Args[1]
file, err := yaml.ReadFile(filename)
if err != nil {
panic(err)
}
value := nodeToList(nodeToMap(file.Root)["bar"])[0]
fmt.Printf("Value: %#v\n", value)
}
To run this sample code, execute following command:
go run src/gypsy.go src/test.yml
Gypsy parser won’t parse following YAML file (because of the indentation of the list which is at the same level than the enclosing map):
foo: 1
bar:
- one
- two
Beego is a build tool, but it includes a low level YAML parser. Mappings are very natural with this parser:
package main
import (
"fmt"
"github.com/beego/goyaml2"
"os"
)
func nodeToMap(node interface{}) map[string]interface{} {
m, ok := node.(map[string]interface{})
if !ok {
panic(fmt.Sprintf("%v is not of type map", node))
}
return m
}
func nodeToList(node interface{}) []interface{} {
m, ok := node.([]interface{})
if !ok {
panic(fmt.Sprintf("%v is not of type list", node))
}
return m
}
func main() {
filename := os.Args[1]
file, err := os.Open(filename)
if err != nil {
panic(err)
}
object, err := goyaml2.Read(file)
if err != nil {
panic(err)
}
value := nodeToList(nodeToMap(object)["bar"])[0]
fmt.Printf("Value: %#v\n", value)
}
This parser is part of a general Go library. This may only parse dictionnaries and its API is a bit tedious.
package main
import (
"fmt"
"github.com/tav/golly/yaml"
"os"
)
func main() {
filename := os.Args[1]
data, err := yaml.ParseFile(filename)
if err != nil {
panic(err)
}
list, ok := data.GetList("bar")
if !ok {
panic("Not OK!")
}
value := list[0].String
fmt.Printf("Value: %#v\n", value)
}
This is a layer around GoYAML to simplify YAML file parsing. You don’t have to describe document structure, you can directly access content exploring the tree. Nevertheless, what you save on one side (not writing the document structure), you loose on the other (writing code to explore the tree and managing errors)…
package main
import (
"fmt"
"github.com/smallfish/simpleyaml"
"io/ioutil"
"os"
)
func main() {
filename := os.Args[1]
source, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
yaml, err := simpleyaml.NewYaml(source)
if err != nil {
panic(err)
}
bar, err := yaml.Get("bar").GetIndex(0).String()
if err != nil {
panic(err)
}
fmt.Printf("Value: %#v\n", bar)
}
The body of the Parser
struct in a TODO comment… Thus seems incomplete and unusable.