TOML Cheatsheet
Arrays and Inline Tables
Use this TOML reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Arrays
Square brackets, comma separated. Values may be any type, including a mix.
integers = [1, 2, 3] colors = ["red", "yellow", "green"] nested = [[1, 2], [3, 4, 5]] nested_mixed = [[1, 2], ["a", "b", "c"]] strings = ["all", 'strings', """are the same""", '''type'''] mixed = [1, "two", 3.0, true, [4]] empty = []
parses to:
{"integers": [1, 2, 3], "colors": ["red", "yellow", "green"],
"nested": [[1, 2], [3, 4, 5]],
"nested_mixed": [[1, 2], ["a", "b", "c"]],
"strings": ["all", "strings", "are the same", "type"],
"mixed": [1, "two", 3.0, true, [4]], "empty": []}Heterogeneous arrays are legal in TOML 1.0.0. They were forbidden in earlier drafts, so older parsers and some Go and Rust libraries still reject them. If a config has to be read by an unknown parser, keep arrays uniform. Whatever deserializes into a typed struct will reject a mixed array anyway.
Multi-line arrays and trailing commas
An array may span lines freely. Newlines and comments are allowed anywhere inside it, and a trailing comma after the last element is allowed.
dependencies = [ "requests>=2.31", # http "pydantic>=2.0", "click>=8.1", # trailing comma below is fine ] matrix = [ [1, 0], [0, 1], ]
This is the main readability win over JSON: a one-line diff when you add a dependency, plus a comment per line saying why it is there.
Inline tables
{ } with key = value pairs. An inline table is a table, identical in the
data model to a [header] block, just written compactly.
name = {first = "Tom", last = "Preston-Werner"}
point = {x = 1, y = 2}
animal = {type = {name = "pug"}}
empty = {}is exactly:
[name] first = "Tom" last = "Preston-Werner" [point] x = 1 y = 2 [animal.type] name = "pug" [empty]
Inline table restrictions
Three hard rules, and all three catch people used to JSON5 or JavaScript.
| Rule | Bad | Error |
|---|---|---|
| single line only | { newline x = 1 } | Invalid initial character for a key part |
| no trailing comma | {x = 1,} | Invalid initial character for a key part |
| immutable once closed | p = {x=1} then [p.q] | Cannot declare ('p', 'q') twice |
| immutable once closed | p = {x=1} then p.y = 2 | Cannot mutate immutable namespace ('p',) |
That immutability is the important one. Once an inline table is written, nothing
may add to it, not a dotted key, not a header, not a nested header. So an inline
table is for a small, complete, final value. Anything you expect to
grow gets a [header].
Arrays of inline tables
The compact alternative to [[header]], good for short uniform rows.
points = [
{x = 1, y = 2, z = 3},
{x = 7, y = 8, z = 9},
]
[[redirects]]
from = "/old"
to = "/new"
status = 301points and a [[points]] block produce identical data. Note the trailing comma
after the last inline table is fine, because that comma belongs to the enclosing
array, not to the inline table. The forbidden case is a comma inside the braces.
Choosing between the four container forms
| You have | Use |
|---|---|
| a list of scalars | tags = ["a", "b"] |
| a long list of scalars | multi-line array, one per line |
| a small fixed record | inline table {x = 1, y = 2} |
| a record with many fields or comments | [header] |
| a few short uniform records | array of inline tables |
| several records with sub-tables | [[header]] |
| something a tool will append to | [[header]], never an array literal |
That last row is the practical rule. A generator can append a new [[x]] block to
the end of a file, but it cannot append to an array literal without rewriting the
value, and it cannot append to an inline table at all.
Whitespace and formatting notes
- Whitespace around =, inside brackets, and around commas is free.
- Inside an inline table, one space after { and before } is the conventional
spelling ({ x = 1 }), but the tight form is equally valid.
- Comments are allowed inside multi-line arrays and not inside inline tables. A
comment runs to end of line, and an inline table cannot contain a newline, so
{ x = 1 # c fails with Unclosed inline table.
- taplo fmt is the usual TOML formatter and taplo lint validates a file against
a schema. cargo fmt formats Rust and never touches Cargo.toml.