TOML (Tom's Obvious, Minimal Language) is a configuration file format designed for clarity and ease of use. This comprehensive guide covers TOML syntax, conversion between TOML/JSON/YAML, best practices, and why TOML has become the preferred choice for modern application configuration.
TOML is a minimal configuration file format created by Tom Preston-Werner (co-founder of GitHub) in 2013. It aims to be easy to read due to obvious semantics, maps unambiguously to hash tables, and is designed specifically for configuration files.
# This is a comment
title = "TOML Example"
name = "Tom Preston-Werner"
age = 27
enabled = true
pi = 3.14159
# Basic strings
str = "I'm a string"
multiline = """
This is a
multiline string.
"""
# Literal strings (no escaping)
path = 'C:\Users\nodejs\templates'
regex = '<\i\c*\s*>'
# Multiline literal strings
winpath = '''C:\Users\
nodejs\templates'''
# Integers
int1 = +99
int2 = 42
int3 = 0
int4 = -17
# Integers with underscores for readability
int5 = 1_000
int6 = 5_349_221
# Hex, octal, binary
hex = 0xDEADBEEF
oct = 0o01234567
bin = 0b11010110
# Floats
float1 = +1.0
float2 = 3.1415
float3 = -0.01
float4 = 5e+22
float5 = 1e06
float6 = -2E-2
# Infinity and NaN
sf1 = inf # positive infinity
sf2 = +inf # positive infinity
sf3 = -inf # negative infinity
sf4 = nan # not a number
bool1 = true
bool2 = false
# Offset datetime
odt1 = 1979-05-27T07:32:00Z
odt2 = 1979-05-27T00:32:00-07:00
odt3 = 1979-05-27T00:32:00.999999-07:00
# Local datetime
ldt1 = 1979-05-27T07:32:00
ldt2 = 1979-05-27T00:32:00.999999
# Local date
ld1 = 1979-05-27
# Local time
lt1 = 07:32:00
lt2 = 00:32:00.999999
# Simple arrays
integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested_arrays = [ [ 1, 2 ], [3, 4, 5] ]
mixed = [ [ 1, 2 ], ["a", "b", "c"] ]
# Multiline arrays
numbers = [
1, 2, 3,
4, 5, 6
]
# Arrays can contain different types
mixed_types = [ 1, "string", true, 3.14 ]
# Trailing commas allowed
fruits = [
"apple",
"banana",
"orange",
]
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
[database]
server = "192.168.1.1"
ports = [ 8000, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
# Inline tables must appear on a single line
animal = { type.name = "pug" } # Invalid - use regular tables instead
[[products]]
name = "Hammer"
sku = 738594937
[[products]]
name = "Nail"
sku = 284758393
color = "gray"
# Equivalent JSON:
# {
# "products": [
# { "name": "Hammer", "sku": 738594937 },
# { "name": "Nail", "sku": 284758393, "color": "gray" }
# ]
# }
TOML:
# Application config
[app]
name = "MyApp"
version = "1.0.0"
[database]
host = "localhost"
port = 5432
credentials = { user = "admin", pass = "secret" }
[[servers]]
name = "alpha"
ip = "10.0.0.1"
[[servers]]
name = "beta"
ip = "10.0.0.2"
JSON (equivalent):
{
"app": {
"name": "MyApp",
"version": "1.0.0"
},
"database": {
"host": "localhost",
"port": 5432,
"credentials": {
"user": "admin",
"pass": "secret"
}
},
"servers": [
{ "name": "alpha", "ip": "10.0.0.1" },
{ "name": "beta", "ip": "10.0.0.2" }
]
}
YAML (equivalent):
app:
name: MyApp
version: 1.0.0
database:
host: localhost
port: 5432
credentials:
user: admin
pass: secret
servers:
- name: alpha
ip: 10.0.0.1
- name: beta
ip: 10.0.0.2
| Feature | TOML | JSON | YAML |
|---|---|---|---|
| Comments | ✓ Yes (#) | ✗ No | ✓ Yes (#) |
| Human Readable | ✓✓ Excellent | ✓ Good | ✓✓ Excellent |
| Datetime Support | ✓ Native | ✗ String only | ✓ Native |
| Ambiguity | ✓ Unambiguous | ✓ Unambiguous | ✗ Can be ambiguous |
| Whitespace Issues | ✓ No issues | ✓ No issues | ✗ Indentation sensitive |
| Verbosity | ✓ Minimal | ✗ Verbose (quotes, braces) | ✓✓ Very minimal |
| Best For | Config files | APIs, data interchange | Complex nested data |
Converting TOML to JSON is straightforward as both formats support similar data types:
# TOML input
[server]
host = "localhost"
port = 8080
[database]
url = "postgres://localhost/db"
# JSON output
{
"server": {
"host": "localhost",
"port": 8080
},
"database": {
"url": "postgres://localhost/db"
}
}
# TOML input
[app]
name = "MyApp"
debug = true
[[servers]]
name = "alpha"
ip = "10.0.0.1"
# YAML output
app:
name: MyApp
debug: true
servers:
- name: alpha
ip: 10.0.0.1
// JSON input
{
"title": "Config",
"owner": {
"name": "Tom",
"age": 27
},
"database": {
"enabled": true
}
}
# TOML output
title = "Config"
[owner]
name = "Tom"
age = 27
[database]
enabled = true
[package]
name = "my-project"
version = "0.1.0"
edition = "2021"
authors = ["Your Name "]
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
[dev-dependencies]
criterion = "0.5"
[profile.release]
opt-level = 3
lto = true
[tool.poetry]
name = "my-package"
version = "0.1.0"
description = "A Python package"
authors = ["Your Name "]
[tool.poetry.dependencies]
python = "^3.9"
requests = "^2.28.0"
pandas = "^1.5.0"
[tool.poetry.dev-dependencies]
pytest = "^7.2.0"
black = "^22.10.0"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
baseURL = "https://example.com/"
title = "My Hugo Site"
theme = "minimal"
[params]
author = "Your Name"
description = "A Hugo website"
dateFormat = "January 2, 2006"
[menu]
[[menu.main]]
name = "Home"
url = "/"
weight = 1
[[menu.main]]
name = "About"
url = "/about/"
weight = 2
[markup]
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true
# Server configuration
[server]
# Listen on all interfaces
host = "0.0.0.0"
# Default HTTP port
port = 8080
# Enable TLS
tls = true # Requires cert.pem and key.pem
[app]
name = "MyApp"
version = "1.0.0"
[app.features]
auth = true
api = true
logging = true
[app.limits]
max_users = 1000
request_timeout = 30
# Good - array of tables
[[users]]
name = "alice"
role = "admin"
[[users]]
name = "bob"
role = "user"
# Avoid - separate numbered keys
[user1]
name = "alice"
[user2]
name = "bob"
[timeouts]
connection = 30 # integer seconds
read = 60
write = 60
[intervals]
heartbeat = 5.5 # float seconds
retry = 2.0
[timestamps]
created = 2026-03-12T10:00:00Z # datetime
expires = 2027-03-12T10:00:00Z
# config.toml (base)
[app]
name = "MyApp"
# config.dev.toml
[app]
debug = true
[database]
url = "localhost:5432"
# config.prod.toml
[app]
debug = false
[database]
url = "prod-db:5432"
connection_pool = 20
import toml
# Parse TOML file
with open('config.toml', 'r') as f:
config = toml.load(f)
print(config['app']['name'])
# Write TOML file
data = {
'app': {
'name': 'MyApp',
'version': '1.0.0'
}
}
with open('output.toml', 'w') as f:
toml.dump(data, f)
use toml::Value;
use std::fs;
fn main() {
let contents = fs::read_to_string("Cargo.toml")
.expect("Failed to read file");
let value = contents.parse::()
.expect("Failed to parse TOML");
println!("{:?}", value["package"]["name"]);
}
const toml = require('toml');
const fs = require('fs');
// Parse TOML
const contents = fs.readFileSync('config.toml', 'utf8');
const config = toml.parse(contents);
console.log(config.app.name);
// Convert to JSON
const json = JSON.stringify(config, null, 2);
fs.writeFileSync('config.json', json);
package main
import (
"fmt"
"github.com/BurntSushi/toml"
)
type Config struct {
Title string
Owner struct {
Name string
Age int
}
}
func main() {
var config Config
_, err := toml.DecodeFile("config.toml", &config)
if err != nil {
panic(err)
}
fmt.Printf("Title: %s\n", config.Title)
}
# Wrong - inline tables must be single line
person = {
name = "Tom",
age = 27
}
# Correct
person = { name = "Tom", age = 27 }
# Or use regular table
[person]
name = "Tom"
age = 27
# Wrong - duplicate keys
name = "Tom"
name = "Jerry" # Error!
# Correct - use different keys or table array
[[person]]
name = "Tom"
[[person]]
name = "Jerry"
# Some parsers allow, but be careful
mixed = [1, "two", 3.0] # May cause issues
# Better - consistent types
integers = [1, 2, 3]
strings = ["one", "two", "three"]
TOML provides the perfect balance between human readability and machine parseability for configuration files. Its minimal syntax, native support for common data types, comment capability, and unambiguous structure make it ideal for modern application configuration. Whether you're working with Rust, Python, or any other language, TOML offers a clear, maintainable way to manage your application's settings.
Use QuickUtil.dev's TOML Converter to easily convert between TOML, JSON, and YAML formats, validate your TOML syntax, and format your configuration files for optimal readability.
TOML (Tom's Obvious, Minimal Language) is a configuration file format designed to be easy to read and write. It uses clear key-value pairs, supports nested structures, and is less verbose than JSON or YAML.
Use a TOML converter tool to parse TOML syntax and output JSON format. TOML's tables become JSON objects, arrays remain arrays, and all data types (string, integer, float, boolean, datetime) convert to their JSON equivalents.
TOML uses explicit key-value pairs with = signs and [sections], while YAML uses indentation. TOML is less ambiguous, easier to parse, and better for config files. YAML is more concise but can have indentation issues.
TOML is more human-readable than JSON, supports comments (JSON doesn't), has cleaner syntax for nested config, built-in datetime support, and is specifically designed for configuration files rather than data interchange.
Cargo (Rust package manager), Poetry (Python dependency manager), Hugo (static site generator), pipenv, and many other modern tools use TOML for configuration files due to its clarity and ease of use.
Arrays in TOML use square brackets: numbers = [1, 2, 3] or strings = ['a', 'b', 'c']. Arrays can be multiline and contain mixed types if needed: mixed = [1, 'two', 3.0].
Yes, TOML supports nested structures using tables. Use [table.subtable] notation or inline tables: parent = { child = 'value' }. Tables can be nested multiple levels deep for complex configurations.
Yes, TOML supports comments using the # character. Comments can appear on their own line or at the end of a line: key = 'value' # This is a comment. This makes TOML excellent for documented configurations.
Convert between TOML, JSON, and YAML formats with ease. Validate syntax, format configuration files, and ensure proper structure.
Try the TOML Converter Now