TOML¶
Model mapping¶
Tables and array-of-tables map directly onto the Document model. A table
becomes a list of edges. [[x]] written twice becomes the label x twice.
| TOML | Document |
|---|---|
a = 1 / b = 2 |
[(a,1),(b,2)] |
[[x]] twice, each with name |
[(x,[(name,"a")]), (x,[(name,"b")])] |
[[x]] is TOML's idiomatic repeated record, and it lands on the
repeated-label shape with no adjustment at all. Of the four non-native
formats, TOML is the one whose own idiom already matches the model.
TOML has native date, time, and datetime literals. All three parse to
the matching types with no schema needed, and write back the same way. TOML is
the one format with no temporal stringification in either direction.
TOML has no null. A null-valued leaf cannot be written. Implementations
MUST report this as a write-time adjustment rather than inventing a
representation.
Top level must be a table. A bare scalar Document cannot be written as TOML.
Interleaving is lost on write, as in the rest of the JSON family.
Worked example¶
The schema:
record Address { "street": string, "city": string }
record LineItem { "sku": string, "qty": integer, "price": number }
record Order {
"id": string,
"status": string,
"total": number,
"address": Address,
"items" [1,]: LineItem,
"coupon" [0,1]: string,
}
record Root { "order": Order }
root Root
The same order in TOML:
[order]
id = "A1"
status = "shipped"
total = 29.97
[order.address]
street = "1 Main"
city = "London"
[[order.items]]
sku = "W"
qty = 3
price = 9.99
[[order.items]]
sku = "G"
qty = 1
price = 9.99
reads to:
[ (order, [ (id, "A1"),
(status, "shipped"),
(total, 29.97),
(address, [ (street, "1 Main"), (city, "London") ]),
(items, [ (sku, "W"), (qty, 3), (price, 9.99) ]),
(items, [ (sku, "G"), (qty, 1), (price, 9.99) ]) ]) ]
The [[order.items]] blocks are the clearest statement in any format of what
"items" [1,]: LineItem means: the label repeats, and there is no list.
[order.address] — a single table, not an array-of-tables — is the [1,1]
case, one edge.
A coupon field would be a plain key inside [order]. Because TOML has no
null, an absent coupon is written by omitting the key, which is what
[0,1] cardinality already means. A null coupon has no TOML spelling at all
and is a write-time adjustment.
A real-world example. pyproject.toml is the canonical case of a
spec'd-open format: its core tables are specified, but [tool.*] is
defined to be open — third-party tools own those subtrees, and a schema
author doesn't get to close them. See pyproject.osd
and its three fixtures in ../examples/,
framed explicitly around where OSD's algebra can't fully capture the
format's own spec.
Parity gaps¶
Chapter 9's status table (§9.3) is the authority. As of spec v0.1, its "Codecs JSON/YAML/TOML/XML" row reads "all four" for Python, TypeScript, and Rust alike — every implementation has a TOML codec.
There is no TOML-specific entry in
§9.4. The null gap
and the table-at-top-level rule are properties of TOML, specified above, not
open questions between implementations.