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, with one
exception: TOML has no time of day with an offset, so a writer writes that as
a quoted ISO-8601 string and reports format.temporal-stringified
(E-37). Every other temporal is
written as its native literal, seconds included, unaltered.
TOML has no null. A null-valued leaf cannot be written, and there is no
substitute value to fall back to — dropping the edge silently would erase
its existence, not just its value. Writing one MUST fail
(write.unsupported-value, C-10), not silently omit it.
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.
Duplicate keys are rejected
(C-12). A table that
defines a key twice (a = 1 then a = 2, a and "a" included) fails the read
with parse.codec-syntax; TOML itself calls it invalid, and Omnist does not
turn it into JSON's last-value-wins
(§ JSON, "Duplicate keys"). The same key in two different tables is
not a repeat, and [[x]] written twice is the repeated-label shape, not a
duplicate.
Integers and floats. TOML hexadecimal (0x), octal (0o) and binary
(0b) integers and _-separated digits are integers like any other, and D-9's
digit limit counts the digits of their value
(D-28): 0b followed by 4 301 ones
is a value of 1 295 decimal digits and is within the default limit. An integer is
arbitrary precision, so one beyond 64 bits is read, not refused. A float literal
beyond binary64's range, 1e999, reads as +Infinity with no diagnostic
(D-29).
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 — writing one fails, it is not written as if it had been omitted.
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 on which implementations ship a TOML codec. This page states no per-port status of its own: a copy here can only go stale relative to the ledger.
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.