TOML¶
Reading uses the standard-library tomllib (Python 3.11+); writing needs
pip install tomli_w.
from omnist import read_toml, Doc
d = Doc(read_toml("""
[order]
id = "A1"
[[order.items]]
sku = "W"
[[order.items]]
sku = "G"
"""))
d.to_json() # '{"order": {"id": "A1", "items": [{"sku": "W"}, {"sku": "G"}]}}'
How it maps¶
- A table becomes a list of edges; nested tables (
[a.b]) nest. - An array-of-tables (
[[order.items]]) is the idiomatic array of records — it maps to a repeateditemslabel, the same as JSON"items": [{…}, {…}].
Read raw, each [[items]] block becomes its own items edge — the repeated
label is in the edge list directly, not just in the regrouped JSON-shaped
projection:
from omnist import read_toml
read_toml("""
[[items]]
sku = "W"
[[items]]
sku = "G"
""")
# [('items', [('sku', 'W')]), ('items', [('sku', 'G')])]
Reading¶
Without a schema¶
Unlike JSON, TOML's grammar has native date/time/datetime literals, and
tomllib parses them straight into the matching Python types — no schema
needed:
from omnist import read_toml
read_toml('d = 2024-01-01')
# [('d', datetime.date(2024, 1, 1))]
type(dict(read_toml('d = 2024-01-01'))['d'])
# <class 'datetime.date'>
read_toml('t = 12:00:00')
# [('t', datetime.time(12, 0))]
read_toml('dt = 2024-01-01T12:00:00')
# [('dt', datetime.datetime(2024, 1, 1, 12, 0))]
This is a genuinely different "before" picture than JSON's: reading TOML
without a schema can already hand back real temporal objects for any of the
three kinds, not just date.
With a schema¶
Because TOML's own parser already produces value-exact date/time/
datetime objects, schema= is a no-op for those fields — it still matters
for upgrading other scalars, e.g. an integer to number:
from omnist import parse_schema, read_toml
s = parse_schema('record R { "d": date, "n": number }\nroot R')
read_toml('d = 2024-01-01\nn = 3', schema=s)
# [('d', datetime.date(2024, 1, 1)), ('n', 3.0)]
See schema-directed deserialization for the full
conversion rules. Doc.from_toml(text, schema=s) is the same conversion
through the Doc wrapper — it just calls read_toml underneath:
from omnist import Doc
Doc.from_toml('d = 2024-01-01\nn = 3', schema=s).to_data()
# [('d', datetime.date(2024, 1, 1)), ('n', 3.0)]
Writing¶
from omnist import write_toml, Doc
write_toml([("id", "A1")]) # 'id = "A1"\n'
Doc.of({"id": "A1"}).to_toml() # 'id = "A1"\n'
No
null. TOML has no null value, so writing one is lenient by default: the edge is dropped and recorded as anull.omittedadjustment (a warning).write_toml(node, report=rep)shows it;strict=TrueraisesWriteErrorinstead. See adjustment reports.Top-level must be a table. A bare scalar or array at the root isn't valid TOML; a single-rooted Document (one top-level key) writes cleanly.
Notes¶
- TOML round-trips
date/time/datetimenatively in both directions — there's notemporal.stringifiedadjustment for TOML the way there is for JSON/XML. - See the comparison table for how TOML's native temporal types and array-of-tables stack up against the other formats.