package toml
import "github.com/BurntSushi/toml"
Package toml implements decoding and encoding of TOML files.
This package supports TOML v1.0.0, as specified at https://toml.io
The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator,
and can be used to verify if TOML document is valid. It can also be used to
print the type of each key.
Example StrictDecoding shows how to detect if there are keys in the TOML
document that weren't decoded into the value given. This is useful for
returning an error to the user if they've included extraneous fields in their
configuration.
Code:play
Output: Example UnmarshalTOML shows how to implement a struct type that knows how to
unmarshal itself. The struct must take full responsibility for mapping the
values passed into the struct. The method may be used with interfaces in a
struct in cases where the actual type is not known until the data is
examined.
Code:play
Example Unmarshaler shows how to decode TOML strings into your own
custom data type.
Code:play
Output:Example (StrictDecoding)¶
package main
import (
"fmt"
"log"
"github.com/BurntSushi/toml"
)
func main() {
var blob = `
key1 = "value1"
key2 = "value2"
key3 = "value3"
`
var conf struct {
Key1 string
Key3 string
}
md, err := toml.Decode(blob, &conf)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Undecoded keys: %q\n", md.Undecoded())
}
Undecoded keys: ["key2"]
Example (UnmarshalTOML)¶
package main
import (
"fmt"
"log"
"github.com/BurntSushi/toml"
)
type order struct {
parts parts
}
type parts []part
type part interface {
Name() string
}
type valve struct {
Type string
ID string
Size float32
Rating int
}
func (v *valve) Name() string {
return fmt.Sprintf("VALVE: %s", v.ID)
}
type pipe struct {
Type string
ID string
Length float32
Diameter int
}
func (p *pipe) Name() string {
return fmt.Sprintf("PIPE: %s", p.ID)
}
type cable struct {
Type string
ID string
Length int
Rating float32
}
func (c *cable) Name() string {
return fmt.Sprintf("CABLE: %s", c.ID)
}
func (o *order) UnmarshalTOML(data any) error {
d, _ := data.(map[string]any)
parts, _ := d["parts"].([]map[string]any)
for _, p := range parts {
typ, _ := p["type"].(string)
id, _ := p["id"].(string)
switch p["type"] {
case "valve":
size := float32(p["size"].(float64))
rating := int(p["rating"].(int64))
valve := &valve{
Type: typ,
ID: id,
Size: size,
Rating: rating,
}
o.parts = append(o.parts, valve)
case "pipe":
length := float32(p["length"].(float64))
diameter := int(p["diameter"].(int64))
pipe := &pipe{
Type: typ,
ID: id,
Length: length,
Diameter: diameter,
}
o.parts = append(o.parts, pipe)
case "cable":
length := int(p["length"].(int64))
rating := float32(p["rating"].(float64))
cable := &cable{
Type: typ,
ID: id,
Length: length,
Rating: rating,
}
o.parts = append(o.parts, cable)
}
}
return nil
}
func main() {
blob := `
[[parts]]
type = "valve"
id = "valve-1"
size = 1.2
rating = 4
[[parts]]
type = "valve"
id = "valve-2"
size = 2.1
rating = 5
[[parts]]
type = "pipe"
id = "pipe-1"
length = 2.1
diameter = 12
[[parts]]
type = "cable"
id = "cable-1"
length = 12
rating = 3.1
`
// See example_test.go in the source for the implementation of the order
// type.
o := &order{}
err := toml.Unmarshal([]byte(blob), o)
if err != nil {
log.Fatal(err)
}
fmt.Println(len(o.parts))
for _, part := range o.parts {
fmt.Println(part.Name())
}
}
Example (Unmarshaler)¶
package main
import (
"fmt"
"log"
"net/mail"
"github.com/BurntSushi/toml"
)
type address struct{ *mail.Address }
func (a *address) UnmarshalText(text []byte) error {
var err error
a.Address, err = mail.ParseAddress(string(text))
return err
}
func main() {
blob := `
contacts = [
"Donald Duck <donald@duckburg.com>",
"Scrooge McDuck <scrooge@duckburg.com>",
]
`
var contacts struct {
// Implementation of the address type:
//
// type address struct{ *mail.Address }
//
// func (a *address) UnmarshalText(text []byte) error {
// var err error
// a.Address, err = mail.ParseAddress(string(text))
// return err
// }
Contacts []address
}
_, err := toml.Decode(blob, &contacts)
if err != nil {
log.Fatal(err)
}
for _, c := range contacts.Contacts {
fmt.Printf("%#v\n", c.Address)
}
}
&mail.Address{Name:"Donald Duck", Address:"donald@duckburg.com"}
&mail.Address{Name:"Scrooge McDuck", Address:"scrooge@duckburg.com"}
Index ¶
- func Marshal(v any) ([]byte, error)
- func PrimitiveDecode(primValue Primitive, v any) error
- func Unmarshal(data []byte, v any) error
- type Decoder
- type Encoder
- type Key
- type Marshaler
- type MetaData
- func Decode(data string, v any) (MetaData, error)
- func DecodeFS(fsys fs.FS, path string, v any) (MetaData, error)
- func DecodeFile(path string, v any) (MetaData, error)
- func DecodeReader(r io.Reader, v any) (MetaData, error)
- func (md *MetaData) IsDefined(key ...string) bool
- func (md *MetaData) Keys() []Key
- func (md *MetaData) PrimitiveDecode(primValue Primitive, v any) error
- func (md *MetaData) Type(key ...string) string
- func (md *MetaData) Undecoded() []Key
- type ParseError
- func (pe ParseError) Error() string
- func (pe ParseError) ErrorWithPosition() string
- func (pe ParseError) ErrorWithUsage() string
- type Position
- type Primitive
- type TextMarshaler
- type TextUnmarshaler
- type Unmarshaler
Examples ¶
- package (StrictDecoding)
- package (UnmarshalTOML)
- package (Unmarshaler)
- Decode
- Encoder.Encode
- MetaData.PrimitiveDecode
Functions ¶
func Marshal ¶
Marshal returns a TOML representation of the Go value.
See Encoder for a description of the encoding process.
func PrimitiveDecode ¶
PrimitiveDecode is an alias for MetaData.PrimitiveDecode().
Deprecated: use MetaData.PrimitiveDecode.
func Unmarshal ¶
Unmarshal decodes the contents of data in TOML format into a pointer v.
See Decoder for a description of the decoding process.
Types ¶
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder decodes TOML data.
TOML tables correspond to Go structs or maps; they can be used interchangeably, but structs offer better type safety.
TOML table arrays correspond to either a slice of structs or a slice of maps.
TOML datetimes correspond to time.Time. Local datetimes are parsed in the local timezone.
time.Duration types are treated as nanoseconds if the TOML value is an integer, or they're parsed with time.ParseDuration() if they're strings.
All other TOML types (float, string, int, bool and array) correspond to the obvious Go types.
An exception to the above rules is if a type implements the TextUnmarshaler interface, in which case any primitive TOML value (floats, strings, integers, booleans, datetimes) will be converted to a []byte and given to the value's UnmarshalText method. See the Unmarshaler example for a demonstration with email addresses.
Key mapping
TOML keys can map to either keys in a Go map or field names in a Go struct. The special `toml` struct tag can be used to map TOML keys to struct fields that don't match the key name exactly (see the example). A case insensitive match to struct names will be tried if an exact match can't be found.
The mapping between TOML values and Go values is loose. That is, there may exist TOML values that cannot be placed into your representation, and there may be parts of your representation that do not correspond to TOML values. This loose mapping can be made stricter by using the IsDefined and/or Undecoded methods on the MetaData returned.
This decoder does not handle cyclic types. Decode will not terminate if a cyclic type is passed.
func NewDecoder ¶
NewDecoder creates a new Decoder.
func (*Decoder) Decode ¶
Decode TOML data in to the pointer `v`.
type Encoder ¶
type Encoder struct { Indent string // string for a single indentation level; default is two spaces. // contains filtered or unexported fields }
Encoder encodes a Go to a TOML document.
The mapping between Go values and TOML values should be precisely the same as for Decode.
time.Time is encoded as a RFC 3339 string, and time.Duration as its string representation.
The Marshaler and encoding.TextMarshaler interfaces are supported to encoding the value as custom TOML.
If you want to write arbitrary binary data then you will need to use something like base64 since TOML does not have any binary types.
When encoding TOML hashes (Go maps or structs), keys without any sub-hashes are encoded first.
Go maps will be sorted alphabetically by key for deterministic output.
The toml struct tag can be used to provide the key name; if omitted the struct field name will be used. If the "omitempty" option is present the following value will be skipped:
- arrays, slices, maps, and string with len of 0
- struct with all zero values
- bool false
If omitzero is given all int and float types with a value of 0 will be skipped.
Encoding Go values without a corresponding TOML representation will return an error. Examples of this includes maps with non-string keys, slices with nil elements, embedded non-struct types, and nested slices containing maps or structs. (e.g. [][]map[string]string is not allowed but []map[string]string is okay, as is []map[string][]string).
NOTE: only exported keys are encoded due to the use of reflection. Unexported keys are silently discarded.
func NewEncoder ¶
NewEncoder create a new Encoder.
func (*Encoder) Encode ¶
Encode writes a TOML representation of the Go value to the Encoder's writer.
An error is returned if the value given cannot be encoded to a valid TOML
document.
Code:play
Output:Example¶
package main
import (
"bytes"
"fmt"
"log"
"time"
"github.com/BurntSushi/toml"
)
func main() {
var (
date, _ = time.Parse(time.RFC822, "14 Mar 10 18:00 UTC")
buf = new(bytes.Buffer)
)
err := toml.NewEncoder(buf).Encode(map[string]any{
"date": date,
"counts": []int{1, 1, 2, 3, 5, 8},
"hash": map[string]string{
"key1": "val1",
"key2": "val2",
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(buf.String())
}
counts = [1, 1, 2, 3, 5, 8]
date = 2010-03-14T18:00:00Z
[hash]
key1 = "val1"
key2 = "val2"
type Key ¶
type Key []string
Key represents any TOML key, including key groups. Use MetaData.Keys to get values of this type.
func (Key) String ¶
type Marshaler ¶
Marshaler is the interface implemented by types that can marshal themselves into valid TOML.
type MetaData ¶
type MetaData struct {
// contains filtered or unexported fields
}
MetaData allows access to meta information about TOML data that's not accessible otherwise.
It allows checking if a key is defined in the TOML data, whether any keys were undecoded, and the TOML type of a key.
func Decode ¶
Decode the TOML data in to the pointer v.
See Decoder for a description of the decoding process.
Code:play
Output:Example¶
package main
import (
"fmt"
"log"
"time"
"github.com/BurntSushi/toml"
)
func main() {
tomlBlob := `
# Some comments.
[alpha]
ip = "10.0.0.1"
[alpha.config]
Ports = [ 8001, 8002 ]
Location = "Toronto"
Created = 1987-07-05T05:45:00Z
[beta]
ip = "10.0.0.2"
[beta.config]
Ports = [ 9001, 9002 ]
Location = "New Jersey"
Created = 1887-01-05T05:55:00Z
`
type (
serverConfig struct {
Ports []int
Location string
Created time.Time
}
server struct {
IP string `toml:"ip,omitempty"`
Config serverConfig `toml:"config"`
}
servers map[string]server
)
var config servers
_, err := toml.Decode(tomlBlob, &config)
if err != nil {
log.Fatal(err)
}
for _, name := range []string{"alpha", "beta"} {
s := config[name]
fmt.Printf("Server: %s (ip: %s) in %s created on %s\n",
name, s.IP, s.Config.Location,
s.Config.Created.Format("2006-01-02"))
fmt.Printf("Ports: %v\n", s.Config.Ports)
}
}
Server: alpha (ip: 10.0.0.1) in Toronto created on 1987-07-05
Ports: [8001 8002]
Server: beta (ip: 10.0.0.2) in New Jersey created on 1887-01-05
Ports: [9001 9002]
func DecodeFS ¶
DecodeFS reads the contents of a file from fs.FS and decodes it with Decode.
func DecodeFile ¶
DecodeFile reads the contents of a file and decodes it with Decode.
func DecodeReader ¶
DecodeReader is an alias for NewDecoder(r).Decode(v).
Deprecated: use NewDecoder(reader).Decode(&value).
func (*MetaData) IsDefined ¶
IsDefined reports if the key exists in the TOML data.
The key should be specified hierarchically, for example to access the TOML key "a.b.c" you would use IsDefined("a", "b", "c"). Keys are case sensitive.
Returns false for an empty key.
func (*MetaData) Keys ¶
Keys returns a slice of every key in the TOML data, including key groups.
Each key is itself a slice, where the first element is the top of the hierarchy and the last is the most specific. The list will have the same order as the keys appeared in the TOML data.
All keys returned are non-empty.
func (*MetaData) PrimitiveDecode ¶
PrimitiveDecode is just like the other Decode* functions, except it decodes a TOML value that has already been parsed. Valid primitive values can *only* be obtained from values filled by the decoder functions, including this method. (i.e., v may contain more Primitive values.)
Meta data for primitive values is included in the meta data returned by the
Decode* functions with one exception: keys returned by the Undecoded method
will only reflect keys that were decoded. Namely, any keys hidden behind a
Primitive will be considered undecoded. Executing this method will update the
undecoded keys in the meta data. (See the example.)
Code:play
Output:Example¶
package main
import (
"fmt"
"log"
"github.com/BurntSushi/toml"
)
func main() {
tomlBlob := `
ranking = ["Springsteen", "J Geils"]
[bands.Springsteen]
started = 1973
albums = ["Greetings", "WIESS", "Born to Run", "Darkness"]
[bands."J Geils"]
started = 1970
albums = ["The J. Geils Band", "Full House", "Blow Your Face Out"]
`
type (
band struct {
Started int
Albums []string
}
classics struct {
Ranking []string
Bands map[string]toml.Primitive
}
)
// Do the initial decode; reflection is delayed on Primitive values.
var music classics
md, err := toml.Decode(tomlBlob, &music)
if err != nil {
log.Fatal(err)
}
// MetaData still includes information on Primitive values.
fmt.Printf("Is `bands.Springsteen` defined? %v\n",
md.IsDefined("bands", "Springsteen"))
// Decode primitive data into Go values.
for _, artist := range music.Ranking {
// A band is a primitive value, so we need to decode it to get a real
// `band` value.
primValue := music.Bands[artist]
var aBand band
err = md.PrimitiveDecode(primValue, &aBand)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s started in %d.\n", artist, aBand.Started)
}
// Check to see if there were any fields left undecoded. Note that this
// won't be empty before decoding the Primitive value!
fmt.Printf("Undecoded: %q\n", md.Undecoded())
}
Is `bands.Springsteen` defined? true
Springsteen started in 1973.
J Geils started in 1970.
Undecoded: []
func (*MetaData) Type ¶
Type returns a string representation of the type of the key specified.
Type will return the empty string if given an empty key or a key that does not exist. Keys are case sensitive.
func (*MetaData) Undecoded ¶
Undecoded returns all keys that have not been decoded in the order in which they appear in the original TOML document.
This includes keys that haven't been decoded because of a Primitive value. Once the Primitive value is decoded, the keys will be considered decoded.
Also note that decoding into an empty interface will result in no decoding, and so no keys will be considered decoded.
In this sense, the Undecoded keys correspond to keys in the TOML document that do not have a concrete type in your representation.
type ParseError ¶
type ParseError struct { Message string // Short technical message. Usage string // Longer message with usage guidance; may be blank. Position Position // Position of the error LastKey string // Last parsed key, may be blank. // Line the error occurred. // // Deprecated: use [Position]. Line int // contains filtered or unexported fields }
ParseError is returned when there is an error parsing the TOML syntax such as invalid syntax, duplicate keys, etc.
In addition to the error message itself, you can also print detailed location information with context by using [ErrorWithPosition]:
toml: error: Key 'fruit' was already created and cannot be used as an array. At line 4, column 2-7: 2 | fruit = [] 3 | 4 | [[fruit]] # Not allowed ^^^^^
[ErrorWithUsage] can be used to print the above with some more detailed usage guidance:
toml: error: newlines not allowed within inline tables At line 1, column 18: 1 | x = [{ key = 42 # ^ Error help: Inline tables must always be on a single line: table = {key = 42, second = 43} It is invalid to split them over multiple lines like so: # INVALID table = { key = 42, second = 43 } Use regular for this: [table] key = 42 second = 43
func (ParseError) Error ¶
func (pe ParseError) Error() string
func (ParseError) ErrorWithPosition ¶
func (pe ParseError) ErrorWithPosition() string
ErrorWithPosition returns the error with detailed location context.
See the documentation on ParseError.
func (ParseError) ErrorWithUsage ¶
func (pe ParseError) ErrorWithUsage() string
ErrorWithUsage returns the error with detailed location context and usage guidance.
See the documentation on ParseError.
type Position ¶
type Position struct { Line int // Line number, starting at 1. Start int // Start of error, as byte offset starting at 0. Len int // Lenght in bytes. }
Position of an error.
func (Position) String ¶
type Primitive ¶
type Primitive struct {
// contains filtered or unexported fields
}
Primitive is a TOML value that hasn't been decoded into a Go value.
This type can be used for any value, which will cause decoding to be delayed. You can use PrimitiveDecode to "manually" decode these values.
NOTE: The underlying representation of a `Primitive` value is subject to change. Do not rely on it.
NOTE: Primitive values are still parsed, so using them will only avoid the overhead of reflection. They can be useful when you don't know the exact type of TOML data until runtime.
type TextMarshaler ¶
type TextMarshaler encoding.TextMarshaler
TextMarshaler is an alias for encoding.TextMarshaler.
Deprecated: use encoding.TextMarshaler
type TextUnmarshaler ¶
type TextUnmarshaler encoding.TextUnmarshaler
TextUnmarshaler is an alias for encoding.TextUnmarshaler.
Deprecated: use encoding.TextUnmarshaler
type Unmarshaler ¶
Unmarshaler is the interface implemented by objects that can unmarshal a TOML description of themselves.
Source Files ¶
decode.go deprecated.go doc.go encode.go error.go lex.go meta.go parse.go type_fields.go type_toml.go
Directories ¶
Path | Synopsis |
---|---|
cmd | |
cmd/toml-test-decoder | Command toml-test-decoder satisfies the toml-test interface for testing TOML decoders. |
cmd/toml-test-encoder | Command toml-test-encoder satisfies the toml-test interface for testing TOML encoders. |
cmd/tomlv | Command tomlv validates TOML documents and prints each key's type. |
_example | |
internal | |
ossfuzz |
- Version
- v1.4.0 (latest)
- Published
- May 23, 2024
- Platform
- linux/amd64
- Imports
- 20 packages
- Last checked
- 17 hours ago –
Tools for package owners.