A little help goes a long way. Find a tool/

Developer FIELD NOTES · 4 MIN READ

TOML to JSON: Seeing Your Config File as Data

Tables become objects, [[blocks]] become arrays, datetimes become strings — the translation rules between TOML and JSON, both directions.

Open almost any modern repository and a TOML file is sitting there — pyproject.toml, Cargo.toml, netlify.toml — while the same project's APIs, logs and test fixtures all speak JSON. The two formats describe exactly the same thing: a tree of keys and values. A converter is therefore a translator between two dialects, and the translation rules are stricter than they first look.

One idea: TOML is a spelling of a hash table

TOML was designed so that every document maps unambiguously onto a hash table — the structure JSON calls an object. That single design decision is why conversion is mostly renaming: = instead of :, bare keys instead of quoted ones, section headers instead of nesting. This TOML:

name = "my-app"

[server]
host = "0.0.0.0"
port = 8080

becomes exactly this JSON, pretty-printed with two-space indent:

{
  "name": "my-app",
  "server": { "host": "0.0.0.0", "port": 8080 }
}

No information is added or lost on the way across — the converter parses the TOML into an in-memory value tree, then serializes that same tree with JSON's punctuation.

Three table shapes, three JSON shapes

TOML has three ways to introduce structure, and each maps to a different JSON shape. A table header like [server] creates (or merges into) an object. An array-of-tables header like [[servers]] appends an object to an array — write the block twice and you get "servers": [ { … }, { … } ], a real JSON array of objects. An inline table like point = { x = 1, y = 2 } stays a compact JSON object on one line. Plain arrays such as tags = ["a", "b"] carry across untouched.

The values that change shape

Most scalars survive intact: booleans, floats, negative numbers, arrays of them. But TOML has niceties JSON lacks, and each is resolved on the JSON side. Integer syntax like underscores and radix prefixes is normalized — 1_000 becomes 1000 and 0xff becomes 255, because JSON has no way to write either. Date and time literals are kept as strings: TOML's 2026-10-24T09:30:00Z arrives in JSON as "2026-10-24T09:30:00Z", since JSON has no native date type. That string convention is what makes a clean round-trip possible — the same text turns back into the same TOML datetime literal.

Going backwards: JSON to TOML

The reverse direction runs the same pipeline the other way. Scalars become key = value lines; nested objects become [table] headers; arrays of objects become [[array-of-tables]] headers; deeply nested objects become dotted header paths (deep.a under a [deep] parent). Strings are emitted as single-quoted literal strings where possible — name = 'my-app' — falling back to double-quoted basic strings with escaping when the content contains a single quote.

One constraint bites: only a JSON object can become TOML. A TOML document's root is always a table, so a top-level array like [1, 2, 3] or a bare scalar has no TOML representation and is rejected with a clear error rather than a silently mangled file. Wrap it in an object first.

What never survives the trip

Comments are the clearest casualty. # deploy target is syntax for humans, not data, so conversion drops it — and a round-trip TOML → JSON → TOML does not restore it. Formatting is re-canonicalized too: blank-line placement, key order and indentation come from the serializer, not your original file. If the comments are the point, keep the TOML file as the source of truth and treat JSON as a read-only view. (Why TOML has comments and JSON deliberately does not is one of the fault lines compared in YAML vs TOML vs JSON; the JSON grammar itself is covered in JSON explained.)

Try it yourself

Paste a real pyproject.toml or Cargo.toml into the TOML to JSON Converter, note how [[blocks]] become JSON arrays, then flip the Direction toggle and send the JSON back — an object-root document round-trips cleanly. To see the third member of the config-language family, convert the same data with the JSON to YAML Converter, and run a YAML file through the YAML Validator to appreciate how much looser a format can be while still parsing.

Frequently asked questions

Why is my JSON rejected when converting to TOML?
TOML's document root is always a table, so only a JSON object has a TOML representation. A top-level array or scalar is rejected with a clear error instead of being silently mangled — wrap it in an object first and it converts.
What happens to TOML datetimes in JSON?
JSON has no native date type, so a TOML datetime like 2026-10-24T09:30:00Z is kept as a string on the JSON side. That convention is what makes a clean round-trip possible: the same text turns back into the same TOML literal.
Are comments and formatting preserved?
No. Comments are syntax for humans, not data, so conversion drops them, and key order and indentation are re-canonicalized by the serializer. If comments matter, keep the TOML file as the source of truth and treat JSON as a read-only view.
How is TOML to JSON different from YAML to JSON?
TOML is stricter: every document maps to a hash table one unambiguous way, so conversion is mostly renaming. YAML has more ways to spell the same data — block and flow styles, multi-line scalars — so its conversions involve more interpretation and more edge cases.