TOML Converter Guide: Master TOML Format for Config Files

By Suvom Das March 12, 2026 9 min read

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.

What is TOML?

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.

Why TOML Matters

TOML Basic Syntax

Key-Value Pairs

# This is a comment
title = "TOML Example"
name = "Tom Preston-Werner"
age = 27
enabled = true
pi = 3.14159

Strings

# 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'''

Numbers

# 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

Booleans

bool1 = true
bool2 = false

Dates and Times

# 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

Arrays

# 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",
]

Tables (Objects/Dictionaries)

Basic Tables

[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

Nested Tables

[servers]

  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"

Inline Tables

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

Array of Tables

[[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 vs JSON vs YAML

Configuration Comparison

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

Format Comparison

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 Between Formats

TOML to JSON

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 to YAML

# 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 to TOML

// JSON input
{
  "title": "Config",
  "owner": {
    "name": "Tom",
    "age": 27
  },
  "database": {
    "enabled": true
  }
}

# TOML output
title = "Config"

[owner]
name = "Tom"
age = 27

[database]
enabled = true

Real-World TOML Examples

Cargo.toml (Rust)

[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

pyproject.toml (Python Poetry)

[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"

Hugo config.toml

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

Best Practices

1. Use Comments Liberally

# 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

2. Group Related Configuration

[app]
name = "MyApp"
version = "1.0.0"

[app.features]
auth = true
api = true
logging = true

[app.limits]
max_users = 1000
request_timeout = 30

3. Use Arrays for Lists

# Good - array of tables
[[users]]
name = "alice"
role = "admin"

[[users]]
name = "bob"
role = "user"

# Avoid - separate numbered keys
[user1]
name = "alice"

[user2]
name = "bob"

4. Leverage Type System

[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

5. Environment-Specific Configs

# 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

Parsing TOML in Different Languages

Python (toml library)

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)

Rust (toml crate)

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"]);
}

JavaScript (toml library)

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);

Go (BurntSushi/toml)

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)
}

Common TOML Mistakes

1. Inline Table Multiline

# 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

2. Duplicate Keys

# Wrong - duplicate keys
name = "Tom"
name = "Jerry"  # Error!

# Correct - use different keys or table array
[[person]]
name = "Tom"

[[person]]
name = "Jerry"

3. Mixed Array Types (when not allowed)

# 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"]

Validation and Tools

Online Validators

IDE Support

Conclusion

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.

Frequently Asked Questions

What is TOML format?

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.

How do I convert TOML to JSON?

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.

What's the difference between TOML and YAML?

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.

Why use TOML instead of JSON for config files?

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.

What projects use TOML?

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.

How do I write arrays in TOML?

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].

Can TOML have nested structures?

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.

Does TOML support comments?

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 TOML to JSON/YAML Instantly

Convert between TOML, JSON, and YAML formats with ease. Validate syntax, format configuration files, and ensure proper structure.

Try the TOML Converter Now