4.2 KiB
TOML parser and encoder for Go with reflection
TOML stands for Tom’s Obvious, Minimal Language. This Go package
provides a reflection interface similar to Go’s standard library
json
and xml
packages. This package also
supports the encoding.TextUnmarshaler
and
encoding.TextMarshaler
interfaces so that you can define
custom data representations. (There is an example of this below.)
Spec: https://github.com/toml-lang/toml
Compatible with TOML version v0.4.0
Documentation: https://godoc.org/github.com/BurntSushi/toml
Installation:
go get github.com/BurntSushi/toml
Try the toml validator:
go get github.com/BurntSushi/toml/cmd/tomlv
tomlv some-toml-file.toml
Testing
This package passes all tests in toml-test for both the decoder and the encoder.
Examples
This package works similarly to how the Go standard library handles
XML
and JSON
. Namely, data is loaded into Go
values via reflection.
For the simplest example, consider some TOML file as just a list of keys and values:
Age = 25
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z
Which could be defined in Go as:
type Config struct {
int
Age []string
Cats float64
Pi []int
Perfection .Time // requires `import time`
DOB time}
And then decoded with:
var conf Config
if _, err := toml.Decode(tomlData, &conf); err != nil {
// handle error
}
You can also use struct tags if your struct field name doesn’t map to a TOML key value directly:
some_key_NAME = "wat"
type TOML struct {
string `toml:"some_key_NAME"`
ObscureKey }
Using the
encoding.TextUnmarshaler
interface
Here’s an example that automatically parses duration strings into
time.Duration
values:
[[song]]
name = "Thunder Road"
duration = "4m49s"
[[song]]
name = "Stairway to Heaven"
duration = "8m03s"
Which can be decoded with:
type song struct {
string
Name
Duration duration}
type songs struct {
[]song
Song }
var favorites songs
if _, err := toml.Decode(blob, &favorites); err != nil {
.Fatal(err)
log}
for _, s := range favorites.Song {
.Printf("%s (%s)\n", s.Name, s.Duration)
fmt}
And you’ll also need a duration
type that satisfies the
encoding.TextUnmarshaler
interface:
type duration struct {
.Duration
time}
func (d *duration) UnmarshalText(text []byte) error {
var err error
.Duration, err = time.ParseDuration(string(text))
dreturn err
}
More complex usage
Here’s an example of how to load the example from the official spec page:
# This is a TOML document. Boom.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# You can indent as you please. Tabs or spaces. TOML don't care.
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]
And the corresponding Go types are:
type tomlConfig struct {
string
Title
Owner ownerInfo`toml:"database"`
DB database map[string]server
Servers
Clients clients}
type ownerInfo struct {
string
Name string `toml:"organization"`
Org string
Bio .Time
DOB time}
type database struct {
string
Server []int
Ports int `toml:"connection_max"`
ConnMax bool
Enabled }
type server struct {
string
IP string
DC }
type clients struct {
[][]interface{}
Data []string
Hosts }
Note that a case insensitive match will be tried if an exact match can’t be found.
A working example of the above can be found in
_examples/example.{go,toml}
.