219 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
## 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](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)
 | 
						|
 | 
						|
Documentation: https://godoc.org/github.com/BurntSushi/toml
 | 
						|
 | 
						|
Installation:
 | 
						|
 | 
						|
```bash
 | 
						|
go get github.com/BurntSushi/toml
 | 
						|
```
 | 
						|
 | 
						|
Try the toml validator:
 | 
						|
 | 
						|
```bash
 | 
						|
go get github.com/BurntSushi/toml/cmd/tomlv
 | 
						|
tomlv some-toml-file.toml
 | 
						|
```
 | 
						|
 | 
						|
[](https://travis-ci.org/BurntSushi/toml) [](https://godoc.org/github.com/BurntSushi/toml)
 | 
						|
 | 
						|
### Testing
 | 
						|
 | 
						|
This package passes all tests in
 | 
						|
[toml-test](https://github.com/BurntSushi/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:
 | 
						|
 | 
						|
```toml
 | 
						|
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:
 | 
						|
 | 
						|
```go
 | 
						|
type Config struct {
 | 
						|
  Age int
 | 
						|
  Cats []string
 | 
						|
  Pi float64
 | 
						|
  Perfection []int
 | 
						|
  DOB time.Time // requires `import time`
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
And then decoded with:
 | 
						|
 | 
						|
```go
 | 
						|
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:
 | 
						|
 | 
						|
```toml
 | 
						|
some_key_NAME = "wat"
 | 
						|
```
 | 
						|
 | 
						|
```go
 | 
						|
type TOML struct {
 | 
						|
  ObscureKey string `toml:"some_key_NAME"`
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### Using the `encoding.TextUnmarshaler` interface
 | 
						|
 | 
						|
Here's an example that automatically parses duration strings into
 | 
						|
`time.Duration` values:
 | 
						|
 | 
						|
```toml
 | 
						|
[[song]]
 | 
						|
name = "Thunder Road"
 | 
						|
duration = "4m49s"
 | 
						|
 | 
						|
[[song]]
 | 
						|
name = "Stairway to Heaven"
 | 
						|
duration = "8m03s"
 | 
						|
```
 | 
						|
 | 
						|
Which can be decoded with:
 | 
						|
 | 
						|
```go
 | 
						|
type song struct {
 | 
						|
  Name     string
 | 
						|
  Duration duration
 | 
						|
}
 | 
						|
type songs struct {
 | 
						|
  Song []song
 | 
						|
}
 | 
						|
var favorites songs
 | 
						|
if _, err := toml.Decode(blob, &favorites); err != nil {
 | 
						|
  log.Fatal(err)
 | 
						|
}
 | 
						|
 | 
						|
for _, s := range favorites.Song {
 | 
						|
  fmt.Printf("%s (%s)\n", s.Name, s.Duration)
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
And you'll also need a `duration` type that satisfies the
 | 
						|
`encoding.TextUnmarshaler` interface:
 | 
						|
 | 
						|
```go
 | 
						|
type duration struct {
 | 
						|
	time.Duration
 | 
						|
}
 | 
						|
 | 
						|
func (d *duration) UnmarshalText(text []byte) error {
 | 
						|
	var err error
 | 
						|
	d.Duration, err = time.ParseDuration(string(text))
 | 
						|
	return err
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### More complex usage
 | 
						|
 | 
						|
Here's an example of how to load the example from the official spec page:
 | 
						|
 | 
						|
```toml
 | 
						|
# 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:
 | 
						|
 | 
						|
```go
 | 
						|
type tomlConfig struct {
 | 
						|
	Title string
 | 
						|
	Owner ownerInfo
 | 
						|
	DB database `toml:"database"`
 | 
						|
	Servers map[string]server
 | 
						|
	Clients clients
 | 
						|
}
 | 
						|
 | 
						|
type ownerInfo struct {
 | 
						|
	Name string
 | 
						|
	Org string `toml:"organization"`
 | 
						|
	Bio string
 | 
						|
	DOB time.Time
 | 
						|
}
 | 
						|
 | 
						|
type database struct {
 | 
						|
	Server string
 | 
						|
	Ports []int
 | 
						|
	ConnMax int `toml:"connection_max"`
 | 
						|
	Enabled bool
 | 
						|
}
 | 
						|
 | 
						|
type server struct {
 | 
						|
	IP string
 | 
						|
	DC string
 | 
						|
}
 | 
						|
 | 
						|
type clients struct {
 | 
						|
	Data [][]interface{}
 | 
						|
	Hosts []string
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
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}`.
 |