toml

A reflection-based TOML decoder and encoder for Go, built to feel like encoding/json.

Library
Go
vv1.6.0
5,027 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
63 /100 Good
Development Activity 40
Maintenance 36
Community 76
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
76 /100 Good
Architecture 78
Code Quality 82
Innovation 55
Learning Curve 90

BurntSushi/toml is a Go library for decoding and encoding TOML documents. It provides a reflection-based API deliberately modeled on Go’s standard library encoding/json and encoding/xml packages, so toml.Decode, toml.Unmarshal, and toml.DecodeFile map values straight onto exported struct fields, with toml:"..." tags available for keys that don’t match Go identifiers directly.

The package targets TOML v1.0.0 compliance and is validated against the official toml-test conformance suite, which ships vendored inside the repo’s internal/toml-test package along with hundreds of valid/invalid fixture files. It also supports encoding.TextUnmarshaler/TextMarshaler and a package-specific Unmarshaler/Marshaler interface pair for custom type conversion, plus a Primitive type for deferring decode decisions until runtime.

Beyond the library, the module ships three CLI tools under cmd/: tomlv, a standalone TOML validator that also prints the inferred type of each key; and toml-test-decoder / toml-test-encoder, harnesses used to run the official toml-test suite against this implementation. As one of the original and most widely depended-on Go TOML libraries, it’s a common transitive dependency across the Go ecosystem, including tools like Hugo and Viper.

What You Get

  • Reflection-based decode/encode API - toml.Decode, toml.Unmarshal, toml.DecodeFile, toml.DecodeFS, and matching Marshal/NewEncoder functions that populate or serialize Go structs directly.
  • Struct tag support - toml:"key_name" tags let TOML keys diverge from Go field naming conventions, matching encoding/json conventions.
  • Custom (un)marshaling interfaces - implement toml.Unmarshaler/Marshaler or the standard encoding.TextUnmarshaler/TextMarshaler interfaces for full control over how a type is decoded or encoded.
  • Primitive deferred-decode type - decode a value into an opaque Primitive and resolve its concrete type later with PrimitiveDecode, avoiding reflection overhead when the shape isn’t known upfront.
  • Detailed ParseError type - structured parse errors carrying message, position (line/column), and last-parsed-key context, with ErrorWithPosition/ErrorWithUsage helpers for pretty-printed diagnostics.
  • Bundled tomlv CLI validator - a standalone command-line tool (cmd/tomlv) that validates a TOML file and can print the inferred type of every key.

Common Use Cases

  • Application configuration files - Go CLIs and servers decode a config.toml straight into a typed config struct at startup.
  • TOML validation in CI/tooling - the bundled tomlv binary is installed and run as a standalone linter/validator step against TOML files without writing any Go code.
  • Round-tripping structured data - encoding Go structs back out to TOML for generated config files, exported settings, or scaffolding templates.
  • Conformance testing other TOML implementations - the toml-test-decoder/toml-test-encoder binaries plug this package into the language-agnostic toml-test suite to validate spec compliance.

Under The Hood

Architecture

The library is organized as a classic lexer/parser/decoder pipeline in a flat package: lex.go tokenizes raw TOML text, parse.go builds an internal tree of parsed values from that token stream, and decode.go walks the parse tree with reflect to populate the caller’s Go value, consulting type_fields.go for struct-tag-aware field resolution and type_toml.go/internal/tz.go for TOML-specific type handling (datetimes, local vs. offset times). encode.go performs the reverse pass, walking a Go value via reflection to emit TOML syntax, and meta.go exposes MetaData so callers can introspect which keys were actually present in the source document after a decode. error.go defines a single structured ParseError type threaded through the lexer and parser so failures carry position and last-key context all the way out to the caller, rather than being flattened into a plain string early. The cmd/ directory layers three thin CLI binaries (tomlv, toml-test-decoder, toml-test-encoder) directly on top of the public package API, and internal/toml-test vendors the official language-agnostic TOML conformance suite (test runner plus hundreds of fixture files) so the parser’s spec compliance is checked mechanically rather than by hand-written cases alone.

Tech Stack

This is a dependency-free Go module (go.mod declares only module github.com/BurntSushi/toml and go 1.21, no third-party requires) targeting TOML v1.0.0 per the package doc comment. It uses only the Go standard library — reflect, encoding, encoding/json (for a compatibility shim), io/io/fs, math, os, strconv, strings, and time — which keeps it trivially embeddable as a transitive dependency without pulling in a wider dependency graph. The CLI tools under cmd/ are plain main packages built with the standard go build/go install toolchain; there’s no external build system, code generator, or ORM/framework layer since this is a pure parsing/serialization library.

Code Quality

Testing is extensive: decode_test.go and encode_test.go alone carry dozens of table-driven test functions covering type coercion, tag handling, and error paths, complemented by lex_test.go, error_test.go, example_test.go (runnable doc examples), a bench_test.go benchmark suite, and fuzz_test.go wired into a dedicated OSS-Fuzz CI workflow (.github/workflows/cifuzz.yml) alongside a standard test.yml CI pipeline. Beyond hand-written Go tests, the package is checked against the vendored official toml-test conformance suite (internal/toml-test), which exercises hundreds of valid/invalid TOML fixtures — a rigor level uncommon even among mature parsing libraries. Error handling is explicit and typed via the structured ParseError (position, last key, message, optional usage guidance) rather than opaque strings, and public functions consistently return error per Go convention. Naming follows idiomatic Go conventions throughout, and a CONTRIBUTING.md documents expectations for contributors.

API Design The public API is deliberately shaped to feel like encoding/json: Decode, Unmarshal, DecodeFile, DecodeFS for reading, Marshal/NewEncoder for writing, and toml:"..." struct tags for key mapping — a Go developer already familiar with the standard library’s JSON package can be productive with almost no new concepts to learn. Extension points follow the same shape as the standard library’s marshaling interfaces (encoding.TextMarshaler/TextUnmarshaler, plus a package-specific Marshaler/Unmarshaler pair), so custom type conversion requires no boilerplate beyond implementing one familiar method. The MetaData return value and Primitive deferred-decode type are the two API surfaces that go beyond a typical JSON library, both addressing TOML-specific needs (detecting which keys were actually set, and delaying decode decisions) without complicating the common-case call. Documentation is strong: doc.go gives a package-level overview, example_test.go provides compiler-checked runnable examples, and the README walks through struct tags and custom unmarshaling with complete code samples.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers