TOML parser for Golang with reflection.

Related tags

Configuration toml
Overview

THIS PROJECT IS UNMAINTAINED

The last commit to this repo before writing this message occurred over two years ago. While it was never my intention to abandon this package, it's clear that I have.

While many issues and PRs have piled up, the most significant short-coming of this library at present is that it has fallen behind the upstream TOML specification.

Many folks are still using this package, and so long as you're happy, there's no pressing reason to switch to something else. With that said, it would probably be wise to organize around an existing alternative or fork this project and update it.

I have no plans on handing ownership of this project over to someone else, unless that someone can meet an extremely high bar that inspires confidence that the project will be in good hands. In particular, I've had mostly poor (but not always) experiences with handing maintenance of a project over to someone else.

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

Build Status GoDoc

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 {
  Age int
  Cats []string
  Pi float64
  Perfection []int
  DOB time.Time // requires `import 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 {
  ObscureKey string `toml:"some_key_NAME"`
}

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 {
  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:

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:

# 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 {
	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}.

Issues
  • Inline Table Support

    Inline Table Support

    Hey, forgive me if I missed this. Recently, inline tables made it into the spec, is this on the roadmap for being supported in this package soon (meaning what kind of priority would supporting inline tables be, if it's one at all)? Just wondering! Also, awesome library!

    opened by ttacon 21
  • Encoder [WIP]

    Encoder [WIP]

    Work-in-progress improvements to the encoder. I'm trying to get it to be fully functioning and would appreciate help and/or code reviews.

    TODOs:

    • [x] Array of tables
    • [ ] Nested arrays of tables
    opened by sqs 15
  • Cannot decode integer value to float64 type.

    Cannot decode integer value to float64 type.

    It seems like a struct containing a float64 field cannot be decoded from a TOML document containing an integer value. The following example demonstrates this.

    package main
    
    import (
        "log"
    
        "github.com/BurntSushi/toml"
    )
    
    func main() {
        raw := "Foo = 123"
        var s struct {
            Foo float64
        }
        _, err := toml.Decode(raw, &s)
        if err != nil {
            log.Fatal(err)
        }
        log.Print(s)
    }
    

    The error message printed looks like this

    2014/09/09 13:42:51 Type mismatch for 'struct { Foo float64 }.Foo': Expected float but found 'int64'.

    opened by bmatsuo 14
  • Using a TextUnmarshaler in a map value doesn't work

    Using a TextUnmarshaler in a map value doesn't work

    Could you explain how to apply this

    func (d *duration) UnmarshalText(text []byte) (err error) {
    	d.Duration, err = time.ParseDuration(string(text))
    	return err
    }
    

    to

    type httpclient struct {
        Timeouts map[string]string
    }
    

    to be able to write in the config like this

    [httpclient.timeouts]
    client = "60s"
    2XX = "50ms"
    3XX = "1000ms"
    4XX = "2000ms"
    5XX = "5000ms"
    

    ?

    bug 
    opened by GarryGaller 12
  • add Marshaler interface

    add Marshaler interface

    Hi @BurntSushi, I've noticed that there is no nice way to handle Marshal/Encode operation unless implementing encoding.TextMarshaler interface, which can't be used if struct should be also marshalable to JSON (json libraries also looks for encoding.TextMarshaler),

    so I've added Marshaler interface with following signature:

    type Marshaler interface {
        MarshalTOML() ([]byte, error)
    }
    

    Also I've added various tests for this feautre.

    opened by kovetskiy 12
  • Add

    Add "extended errors"

    The lexer and parser now always return a ParseError; the Error() method is mostly unchanged:

    toml: line 1 (last key "x.key"): newlines not allowed within inline tables
    

    This adds an ErrorWithLocation() method, which will add some context where the error occurred, similar to e.g. clang or the Rust compiler:

    toml: error: newlines not allowed within inline tables
    
    At line 1, column 18:
    
          1 | x = [{ key = 42 #
    			   ^
    

    And the ErrorWithUsage() also adds some usage guidance (not always present):

    toml: error: newlines not allowed within inline tables
    
    At line 1, column 16:
    
          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
    

    The line/column information should now also always be correct, and a number of error message have been tweaked a bit.

    Fixes #201 Fixes #217

    opened by arp242 11
  • Support for delayed parsing or unification of sections

    Support for delayed parsing or unification of sections

    I have some occasions there I might have a few sections of configuration that map to modules in a system that are not coupled with the top-level configuration loader. These sections could be considered to need somewhat dynamic unification.

    With JSON it's rather easy since one can simply put placeholders using json.RawMessage. Which allows those sections of the document to be delayed. Would you consider accepting something like a toml.RawSection or similar?

    In the meantime I've resorted to hardcoding these subsections but it's brittle and requires constant edits to ensure the compiled in packages that implement this special submodule interface are included properly in the configuration. I could also parse to a generic map and unify by hand but this results in a lot of ugly boilerplate code that has to repeated for each section type.

    opened by cararemixed 11
  • switch to MIT license

    switch to MIT license

    The WTFPL causes people to not want to use this library. Historically, I've been against changing the license mostly because it's just a pain to do so. Ideally, we'd like to get a sign off from all people that have made non-trivial contributions. (And if we can't, we either need to stop the re-licensing process or remove/rewrite those contributions. I'm not particularly inclined to the do latter, but if we can do the former, than we should.)

    So, this issue is going to track the relicensing progress. I'll start by listing some of the major contributors, where I interpreted "major" as "100 lines of code or more."

    • [x] @BurntSushi
    • [x] @cespare
    • [x] @sqs
    • [x] @rjeczalik
    • [x] @ttacon
    • [x] @bbuck
    • [x] @halostatue
    • [x] @sethwklein
    opened by BurntSushi 10
  • panic runtime error while unmarshal `bad-utf8-at-end.toml` on go 1.17

    panic runtime error while unmarshal `bad-utf8-at-end.toml` on go 1.17

    Hi! thanks a lot for this useful package!

    but we got a problem with BurntSushi/toml. There is a panic while unmarshal bad-utf8-at-end.toml from your tests on go 1.17.

    it seems that runtime.panic was changes: cmd/compile,runtime: provide index information on bounds check failure. and this check doesn't work now: https://github.com/BurntSushi/toml/blob/9be4ccf5153f55ef1032bdf52d01e65ea480380b/parse.go#L28

    For reproduce I wrote next sample:

    	b, _ := ioutil.ReadFile("bad-utf8-at-end.toml")
    	var v interface{}
    	if err := toml.Unmarshal(b, &v); err != nil {
    		log.Fatalf("toml.Unmarshal error: %v", err)
    	}
    

    Result:

    panic: runtime error: slice bounds out of range [238:237] [recovered]
            panic: runtime error: slice bounds out of range [238:237]
    
    goroutine 1 [running]:
    github.com/BurntSushi/toml.parse.func1()
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/parse.go:46 +0x16a
    panic({0x5072a0, 0xc000148018})
            /usr/local/go/src/runtime/panic.go:1047 +0x262
    github.com/BurntSushi/toml.(*lexer).current(0xc000150000)
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/lex.go:129 +0x90
    github.com/BurntSushi/toml.(*lexer).emit(0xc000150000, 0x6)
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/lex.go:133 +0x27
    github.com/BurntSushi/toml.lexMultilineString(0xc000150000)
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/lex.go:693 +0x2f1
    github.com/BurntSushi/toml.(*lexer).nextItem(0xc000150000)
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/lex.go:98 +0xf9
    github.com/BurntSushi/toml.(*parser).next(0xc0001401c0)
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/parse.go:95 +0x55
    github.com/BurntSushi/toml.(*parser).topLevel(0xc0001401c0, {0x12, {0xc00014c100, 0x0}, 0x5})
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/parse.go:172 +0x732
    github.com/BurntSushi/toml.parse({0xc00014c100, 0xf2})
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/parse.go:79 +0x4f5
    github.com/BurntSushi/toml.(*Decoder).Decode(0xc000116350, {0x4f7360, 0xc000116340})
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/decode.go:120 +0x625
    github.com/BurntSushi/toml.Decode({0xc00014c000, 0xf2}, {0x4f7360, 0xc000116340})
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/decode.go:135 +0x10f
    github.com/BurntSushi/toml.Unmarshal({0xc00014a000, 0xf2, 0x200}, {0x4f7360, 0xc000116340})
            /home/home/go/pkg/mod/github.com/!burnt!sushi/[email protected]/decode.go:23 +0x85
    main.main()
            /home/home/t/main.go:12 +0xe5
    

    upd: I can try to create a PR for fix it )

    bug 
    opened by afdesk 9
  • Fix override map element value during decode

    Fix override map element value during decode

    I have map, that has structures as elements.

    type LogConfig struct {
         Filename string  `toml:"file"`
         Level       string  `toml:"level"`
    }
    
    type Config struct {
        Loggers map[string]*LogConfig `toml:"log"`
    }
    
    fun NewConfig() *Config {
        return &Config{
             Loggers: map[string]*LogConfig {
                     "error": &LogConfig{Level: "error"},
                     "access": &LogConfig{Level: "info"},
            }
    }
    
    cfg := NewConfig()
    toml.DecodeFile("config.toml", &cfg)
    

    And If I do not specify the both "level and file" in config, I lose the defaults with I specify on creating Config.

    I expected that level will keep origin value if it is not specified in config.toml

    opened by bgaifullin 9
  • added support and tests for multiline string encoding closes BurntSushi/toml#64

    added support and tests for multiline string encoding closes BurntSushi/toml#64

    I would like to propose a solution to encoding multiline strings and raw multiline strings that I had raised in the issue BurntSushi/toml#64.

    The proposal is to accept a new struct tag modifier which can take values of "multiline_string" or "multiline_rawstring" (exported as constants MOD_MULTILINE_STRING and MOD_MULTILINE_RAWSTRING). On detecting presence of either of these modifiers, the type of the struct member is checked to confirm to reflect.String and then the Key.String() to which the modifier applies is inserted into a new map attribute of Encoder called modifiers.

    In the functions that actually process and emit the key/value (in this case in keyEqElement) we can check for presence of the key being processed currently in modifiers and if the modifier is MOD_MULTILINE_STRING or MOD_MULTILINE_RAWSTRING, the element is written by the new writeMultiLineString() function. The reason for choosing the route of using an additional encoder attribute is that Key is currently implemented as []string which makes it difficult to store modifiers with the Key itself.

    The same concept can be extended to any other output modifiers if necessary even in the future. I have added tests for multiline string encoding currently in the encode_test.go file (not yet figured out the toml-test package) and still need to writeup documentation but would like to seek review of the proposal

    opened by srinathh 9
  • Parsing toml files does not always produce the expected results

    Parsing toml files does not always produce the expected results

    This is source code:

    package main
    
    import (
    	"fmt"
    
    	"github.com/BurntSushi/toml"
    )
    
    type Config struct {
    	StartTime string `toml:"start-time"`
    	EndTime string `toml:"end-time"`
    	Format string `toml:"format"`
    	//Interval time.Duration `toml:"internal"`
    	MetricBatchSize int `toml:"metric-batch-size"`
    	InfluxDB InfluxDB `toml:"influxdb"`
    	Streams []Stream `toml:"stream"`
    }
    
    type InfluxDB struct {
    	Urls []string `toml:"urls"`
    	Database string `toml:"database"`
    	RetentionPolicy string `toml:"retention-policy"`
    	Timeout int `toml:"timeout"`
    }
    
    type Stream struct {
    	//Interval time.Duration `toml:"internal"`
    	Measurement string `toml:"measurement"`
    	Tag []Tag `toml:"tag"`
    	Field []Field `field:"field"`
    }
    
    type Tag struct {
    	Key string
    	Value []string
    	ValuesTag int
    	
    }
    
    type Field struct {
    	Key string
    	Value []interface{}
    	ValuesTag int
    	ValueType string
    }
    
    func main() {
    	var config Config
    	if _, err := toml.DecodeFile("etc/sample.conf", &config); err != nil {
    
    	}
    	fmt.Printf("startTime: %v\n", config.StartTime)
    }
    

    This is the toml file in the code:

    # global
    
    # Data generation interval
    interval= "10"
    ## metric_batch_size metrics.
    metric-batch-size= "5000"
    # start-time
    start-time= "2022-01-01T00:00:00Z"
    
    # end-time
    end-time= "2022-01-02T00:00:00Z"
    
    # format default rfc3339
    format = "rfc3339"
    
    
    [influxdb]
    urls = ["http://127.0.0.1:8086"]
    database = "telegraf"
    retention-policy = ""
    timeout = "5s"
    

    I ran it more than ten times, and only two times returned the correct results:

    ➜  stream-gen git:(main) ✗ go run main.go       
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 2022-01-01T00:00:00Z
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 2022-01-01T00:00:00Z
    ➜  stream-gen git:(main) ✗ go run main.go
    startTime: 
    

    environmental information:

    Golang Version: go1.18.3 darwin/arm64

    github.com/BurntSushi/toml v1.2.0

    opened by IvanGao01 1
  • Encoding: 'omitempty' will panic if the struct contains a uncomparable type

    Encoding: 'omitempty' will panic if the struct contains a uncomparable type

    While encoding a struct will be checked for emptiness with the isEmpty function:

    func isEmpty(rv reflect.Value) bool {
    	switch rv.Kind() {
    	case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
    		return rv.Len() == 0
    	case reflect.Struct:
    		return reflect.Zero(rv.Type()).Interface() == rv.Interface()
    	case reflect.Bool:
    		return !rv.Bool()
    	}
    	return false
    }
    

    The comparing of structs panics if the structs contains any uncomparable type.

    Minimal example:

    type a struct {
    	B b `toml:"B,omitempty"`
    }
    
    type b struct {
    	C []string `toml:"C,omitempty"`
    }
    
    func TestToml(t *testing.T) {
    	b1 := b{C: []string{"foo"}}
    	a1 := a{B: b1}
    	var buf bytes.Buffer
    	toml.NewEncoder(&buf).Encode(a1)
    	fmt.Printf("%s", buf.String())
    }
    

    Output:

    === RUN   TestToml
    --- FAIL: TestToml (0.00s)
    panic: runtime error: comparing uncomparable type data.b [recovered]
    	panic: runtime error: comparing uncomparable type data.b [recovered]
    	panic: runtime error: comparing uncomparable type data.b
    
    opened by ybaldus 12
  • the unmarshal and decode API are wasteful and somewhat misleading

    the unmarshal and decode API are wasteful and somewhat misleading

    Hi, I was just looking at ways the unmarshalling and decoding is handled by this package. I must say im a bit terrifed with what I saw.

    So Unmarshalconverts bytes to string and passes it to Decode

    func Unmarshal(p []byte, v interface{}) error {
    	_, err := Decode(string(p), v)
    	return err
    }
    

    Then Decodeconverts the string to io.Reader and creates a new Decoder

    func Decode(data string, v interface{}) (MetaData, error) {
    	return NewDecoder(strings.NewReader(data)).Decode(v)
    }
    

    Finally, decoder.Decode, uses io.ReadAll to read everything into []bytes and converts it back into a string before calling parse.

    data, err := ioutil.ReadAll(dec.r)
    if err != nil {
    	return MetaData{}, err
    }
    p, err := parse(string(data))
    if err != nil {
    	return MetaData{}, err
    }
    

    So it seems like using the Unmarshal function is pretty wasteful since it does this coversion roudtrip.

    Additionally. it is not possible to use the decoder created by NewDecoder in a true decoder fashion, since usually it is read until EOF or another error. But EOF is never returned by decoder.Decode.

    So, the below will just hang. Although it is the expected way to use a decoder.

    for {
        if err := dec.Decode(&data); err == io.EOF {
            break
        } else if err != nil {
            panic(err)
        }
    }
    
    v2 
    opened by bluebrown 3
  • Support encoding comments and specifying the encoding format

    Support encoding comments and specifying the encoding format

    This allows encoding comments and setting some flags to control the format. While toml.Marshaler added in #327 gives full control over how you want to format something, I don't think it's especially user-friendly to tell everyone to create a new type with all the appropriate formatting, escaping, etc. The vast majority of of use cases probably just call in to a few simple categories such as "use """ or "encode this number as a hex".

    I grouped both features together as they're closely related: both set additional information on how to write keys.

    What I want is something that:

    1. allows setting attributes programmatically;
    2. supports round-tripping by default on a standard struct;
    3. plays well with other encoders/decoders;
    4. has a reasonable uncumbersome API.

    Most options (custom types, struct tags) fail at least one of these; there were some PRs for struct tags, but they fail at 1, 2, and (arguably) 4. Custom types fail at 2, 3, and probably 4.


    This adds SetMeta() to the Encoder type; this is already what we have when decoding, and all additional information will be set on it. On MetaData we add the following types:

    SetType()       Set TOML type info.
    TypeInfo()      Get TOML type info.
    Doc()           Set "doc comment" above the key.
    Comment()       Set "inline comment" after the key.
    

    Every TOML type has a type in this package, which support different formatting options (see type_toml.go):

    Bool
    String
    Int
    Float
    Datetime
    Table
    Array
    ArrayTable
    

    For example:

    meta := toml.NewMetaData().
            SetType("key", toml.Int{Width: 4, Base: 16}).
            Doc("key", "A codepoint").
    Comment("key", "ë")
    toml.NewEncoder(os.Stdout).SetMeta(meta).Encode(struct {
            Key string `toml:"key"`
    }{"ë")
    

    Would write:

    # A codepoint.
    key = 0x00eb  # ë
    

    It also has Key() to set both:

    toml.NewMetaData().
        Key("key", toml.Int{Width: 4, Base: 16}, toml.Doc("A codepoint"), toml.Comment("ë")).
        Key("other", toml.Comment("..."))
    

    The advantage of this is that it reduces the number of times you have to type the key string to 1, but it uses interface{}. Not yet decided which one I'll stick with, and also not a huge fan of Doc() and Comment(), but I can't really think of anything clearer at the moment (these are the names the Go ast uses).


    The Decode() sets all this information on the MetaData, so this:

    meta, _ := toml.Decode(..)
    toml.NewEncoder(os.Stdout).SetMeta(meta).Encode(..)
    

    Will write it out as "key = 0x00eb" again, rather than "key = 235".

    This way, pretty much any flag can be added programmatically without getting in the way of JSON/YAML/whatnot encoding/decoding.


    I don't especially care how you need to pass the keys as strings, but there isn't really any good way to do it otherwise. There is also the problem that the "key" as found in the parser may be different than the "key" the user is expecting if you don't use toml struct tags:

    type X struct { Key int }
    

    Will read "key = 2" in to "Key", but when encoding it will write as "Key" rather than "key". The type information will be set to "key", but when encoding it will look for "Key", so round-tripping won't work correct and has the potential for confusion if the wrong key is set.

    This is not so easy to fix since we don't have access to the struct in the parser. I think it's fine to just document this as a caveat and tell people to use struct tags, which is a good idea in any case.


    I'm not necessarily opposed to also adding struct tags for most of these things, although I'm not a huge fan of them. Since struct tags can't be set programmatically it's not really suitable for many use cases (e.g. setting comments dynamically, using multiline strings only if the string contains newlines, etc.) It's something that could maybe be added in a future PR, if a lot of people ask for it.

    Fixes #64 Fixes #75 Fixes #160 Fixes #192 Fixes #213 Fixes #269

    v2 
    opened by arp242 3
  • Require 2-digit hour for local time

    Require 2-digit hour for local time

    Given a=1:32:00, this package returns a valid time-local value instead of returning an error.

    Reproduction

    https://play.golang.org/p/fciY3UVyoT6

    toml.Unmarshal([]byte("a=1:32:00"), &v)
    

    Or using the toml-test decoder:

    $ echo "a=1:32:00" | toml-test-decoder2
    {
      "a": {
        "type": "time-local",
        "value": "01:32:00"
      }
    }
    
    bug 
    opened by moorereason 3
Releases(v1.2.0)
  • v1.2.0(Jul 20, 2022)

    This release adds a few additional features:

    • Support encoding and decoding json.Number, making interoperability with JSON when using json.Encoder.UseNumber() easier.

    • Support time.Duration string format; an integer will be interpreted as nanoseconds (like before), but a string like "5h" will be parsed. On encoding the string format is used.

    • The omitempty struct tag now also works for structs with all zero values, for example an empty time.Time. A struct is considered "empty" when all fields (exported and private) are the zero value.

    • Allow using interface{} (or any) as the map key when decoding.

    And some fixes:

    • Fix encoding.TextUnmarshaler not working for map values.

    • Make encoding.TextUnmarshaler and toml.Unmarshaler work if MarshalText() or MarshalTOML() have a pointer receiver.

    • Error out on nil returns from MarshalTOML/MarshalText; before they would get encoded as invalid TOML (keyname =).

    • Fix a panic where it would try to encode array = [{}, 0] as:

      [[array]]
      [[array]]
      

      Which isn't valid as 0 isn't a table.

    • Some better error reporting for some errors.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Apr 4, 2022)

    Just a few bugfixes:

    • Skip fields with toml:"-" even when they're unsupported types. Previously something like this would fail to encode due to func being an unsupported type:

      struct {
          Str  string `toml:"str"
          Func func() `toml:"-"`
      }
      
    • Multiline strings can't end with \. This is valid:

      # Valid
      key = """ foo \
      """
      
      # Invalid
      key = """ foo \ """
      
    • Don't quote values in TOMLMarshaler. Previously they would always include quoting (e.g. "value"), while the entire point of this interface is to bypass that.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jan 12, 2022)

    This release adds much more detailed errors, support for the toml.Marshaler interface, and several fixes.

    There is no special meaning in the jump to v1.0; the 0.x releases were always treated as if they're 1.x with regards to compatibility; the versioning scheme for this library predates the release of modules.

    New features

    • Error reporting is much improved; the reported position of errors should now always be correct and the library can print more detailed errors (#299, #332)

      Decode always return a toml.ParseError, which has three methods:

      • Error() behaves as before and shows a single concise line with the error.

      • ErrorWithPosition() shows the same error, but also shows the line the error occurred at, similar to e.g. clang or the Rust compiler.

      • ErrorWithUsage() is the same as ErrorWithPosition(), but may also show a longer usage guidance message. This isn't always present (in which case it behaves identical to ErrorWithPosition()), but it should be present for most common mistakes and sources of confusion.

      Which error the correct one to use is depends on your application and preferences; in general I would recommend using at least ErrorWithPosition() for user-facing errors, as it's much more helpful for users of any skill level. If your users are likely to be non-technical then ErrorWithUsage() is probably a good idea; I did my best to avoid technical jargon such as "newline" and phrase things in a way that's understandable by most people not intimately familiar with these sort of things.

      Additionally, the TOML key that fialed should now always be reported in all errors.

    • Add toml.Marshaler interface. This can be used if you want full control over how something is marshalled as TOML, similar to json.Marshaler etc. This takes precedence over encoding.TextMarshaler. (#327)

    • Allow TOML integers to be decoded to a Go float (#325)

      Previously int = 42 could only be decoded to an int* type; now this can also be decoded in a float type as long as it can be represented without loss of data.

    Fixes

    • Key.String() is now quoted when needed (#333)

    • Fix decoding of nested structs on 32bit platforms (#314)

    • Empty slices are now always []T{} rather than nil, which was the behaviour in v0.3.1 and before. While they are identical for most purposes, encoding/json encodes them different ([] vs. null), making it an (accidentally) incompatible change (#339)

    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Aug 5, 2021)

    This fixes a cyclic module dependency issue with github.com/BurntSushi/toml-test that prevented some people from updating. See #313 for some details.

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Aug 2, 2021)

    After some time of inactivity this package is now maintained again.

    This release should support alll of TOML 1.0 and has various bugfixes and a few small improvements.

    This requires Go 1.13 or newer; older Go versions will no longer work.

    TOML 1.0 support

    Previously this library implemented TOML 0.3; now all of TOML 1.0 is supported:

    • Support dotted keys (a.b = 1, a = {b.c = 2}).

    • Mixed arrays: in previous TOML versions array values all had to be of the same type; you can now freely mix types, including inline tables.

    • Support hex (0x2f9a), binary (0b0110), and octal (0o777) literals, and support nan and inf for floats.

    • Support local datetimes, dates, and times. These are dates and times without a timezone and are parsed in the local timezone.

    • Allow accidental whitespace between backslash and newline in the line continuation operator in multi-line basic strings.

    There should be no incompatibilities as such; all existing valid TOML files should continue to work. However, the parser previously allowed the following invalid values:

    • It would allow literal control characters in strings.

    • It would allow leading zeroes in decimal ints and floats.

    Neither of these was ever valid TOML, and are explicitly forbidden by the specification. But the library erroneously permitted them.

    Other changes

    • Set up Go modules.

    • Allow escaping the \, and allow triple-quotes strings to end with a quote (e.g. x="""x"""").

    • All control characters inside strings are properly escaped when encoding.

    • Support encoding nested anonymous structs.

    • Encode toml.Primitive values.

    • You get a more helpful error on UTF-16 files (probably the most common non-UTF-8 compatible encoding). Also read over UTF-16 BOM in UTF-8 files.

    • Call MarshalText and UnmarshalText consistently on all types; before this didn't always happen in some cases.

    • Allow empty quoted keys ("" = 1); silly, but explicitly mentioned as valid.

    • Don't panic in encoder on unsupported types; return an error instead.

    • Don't panic on unclosed inline arrays.

    • Add Decoder and deprecate DecodeReader(); this is more consistent with how other decoders tend to work and allows adding decoding options.

    • Add DecodeFS() for Go 1.16 or newer.

    • Avoid creating new functions/allocations in lexSkip; small performance improvement.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Aug 29, 2014)

Owner
Andrew Gallant
I love to code.
Andrew Gallant
Golang Configuration tool that support YAML, JSON, TOML, Shell Environment

Configor Golang Configuration tool that support YAML, JSON, TOML, Shell Environment (Supports Go 1.10+) Usage package main import ( "fmt" "github.c

Jinzhu 1.5k Aug 11, 2022
Library providing routines to merge and validate JSON, YAML and/or TOML files

CONFLATE Library providing routines to merge and validate JSON, YAML, TOML files and/or structs (godoc) Typical use case: Make your application config

Andy 25 May 5, 2022
Light weight, extensible configuration management library for Go. Built in support for JSON, TOML, YAML, env, command line, file, S3 etc. Alternative to viper.

koanf (pronounced conf; a play on the Japanese Koan) is a library for reading configuration from different sources in different formats in Go applicat

Kailash Nadh 1.1k Aug 8, 2022
Go library for the TOML language

go-toml Go library for the TOML format. This library supports TOML version v1.0.0-rc.3 Features Go-toml provides the following features for using data

Thomas Pelletier 1.3k Aug 10, 2022
Generic templating tool with support of JSON, YAML and TOML data

gotempl Small binary used to generate files from Go Templates and data files. The following formats are supported: JSON YAML TOML Usage usage: gotempl

Link Society 7 Jun 15, 2022
Tmpl - A tool to apply variables from cli, env, JSON/TOML/YAML files to templates

tmpl allows to apply variables from JSON/TOML/YAML files, environment variables or CLI arguments to template files using Golang text/template and functions from the Sprig project.

krako 1 May 30, 2022
ini parser for golang

INI Parser & Write Library ini parser and write library for Golang,easy-use,fast Features Can be read by []byte Can be read by file Supports file moni

levene 9 Apr 6, 2022
Nginx Configuration Golang Parser

Nginx Configuration Golang Parser

faceair 8 Jun 29, 2022
🔎🪲 Malleable C2 profiles parser and assembler written in golang

goMalleable ?? ?? Malleable C2 profiles parser and assembler written in golang Table of Contents Introduction Installation Usage Examples Introduction

Georgy Gennadev 12 Jul 5, 2022
A simple INI file parser and builder.

ini A simple INI file parser and builder. What Read INI files, or build them section by section. Datatypes are kept very simple. The main fuctions are

Grimdork.net 1 Nov 20, 2021
parser for configuration files

config-loader config-loader supports to load config files and convert to map values. Supported format json Usage import ( "fmt" "github.com/tharun2

Tharun Rajendran 0 Nov 27, 2021
Go-config - Config parser for go that supports environment vars and multiple yaml files

go-multiconfig This package is able to parse yaml config files. It supports gett

Dimitris Tassopoulos 1 Jun 23, 2022
✨Clean and minimalistic environment configuration reader for Golang

Clean Env Minimalistic configuration reader Overview This is a simple configuration reading tool. It just does the following: reads and parses configu

Ilya Kaznacheev 686 Aug 8, 2022
Genv is a library for Go (golang) that makes it easy to read and use environment variables in your projects. It also allows environment variables to be loaded from the .env file.

genv Genv is a library for Go (golang) that makes it easy to read and use environment variables in your projects. It also allows environment variables

Şakir Şensoy 28 Jul 9, 2022
Golang library for managing configuration data from environment variables

envconfig import "github.com/kelseyhightower/envconfig" Documentation See godoc Usage Set some environment variables: export MYAPP_DEBUG=false export

Kelsey Hightower 4.2k Aug 15, 2022
A golang package for parsing ini-style configuration files

Mini Mini is a simple ini configuration file parser. The ini syntax supported includes: The standard name=value Comments on new lines starting with #

Stephen Asbury 31 Jul 7, 2022
A better way to marshal and unmarshal YAML in Golang

YAML marshaling and unmarshaling support for Go Introduction A wrapper around go-yaml designed to enable a better way of handling YAML when marshaling

Sam Ghods 934 Aug 7, 2022
🔥🔥 🌈 Golang configuration,use to Viper reading from remote Nacos config systems. Viper remote for Naocs.

Viper remote for Nacos Golang configuration,use to Viper reading from remote Nacos config systems. Viper remote for Naocs. runtime_viper := viper.New(

yoyofxteam 20 Jul 30, 2022