TOML to CSV Converter
A TOML to CSV converter turns a config file into a spreadsheet. The hard part is deciding which part of the tree is the table, and this one picks the array of tables that is actually your data rather than the first one it trips over, names every alternative it found, and reads a config with no repeated section as a single row of dotted keys. Nothing is uploaded.
Want to filter or join the result? Open the app
Which part of the file is the table?
TOML is a tree and a CSV is a rectangle, so something has to decide which branch of the tree is row shaped. A real file usually has more than one candidate.
Take a pyproject.toml. It has [[tool.poetry.source]] with two entries near the top, and it might have [[tool.poetry.packages]] with three, and the thing you actually came for could be a [[dependencies]] array with two hundred. A converter that takes the first array of tables it encounters hands you the two-entry source block and calls it a day.
The rule here is: prefer arrays at the top level, and among the candidates pick the one with the most entries. That gets it right on nearly every real file, because the data is usually the big thing and the metadata is usually nested. Then it tells you what it did:
This file holds 2 arrays of tables (tool.poetry.source with 2 entries,
services with 5 entries). The one with the most entries at the shallowest
level was used: services. Name a different one below to switch.
Every candidate is named with its dotted path and its size, so if the guess is wrong you can see immediately what the alternative is and type its path in. Naming a path that does not exist lists what does rather than failing blankly.
A worked example
A deployment manifest:
title = "Billing platform"
owner = "platform-team"
[[services]]
name = "billing-api"
replicas = 4
cpu_limit = 1.5
public = true
region_code = "01730"
released = "2024-11-03"
[[services]]
name = "invoice-worker"
replicas = 2
cpu_limit = 0.5
public = false
region_code = "00412"
released = "2024-09-17"
comes back as:
name,replicas,cpu_limit,public,region_code,released
billing-api,4,1.5,true,01730,2024-11-03
invoice-worker,2,0.5,false,00412,2024-09-17
The title and owner keys at the top level are not columns, because they are document metadata rather than per-row values, and repeating them on every row would be inventing data. The region_code keeps its leading zeros, because it was a quoted string in the source and everything arrives in the CSV as text.
A nested table inside each entry flattens with dot notation, so a [services.resources] block with cpu and memory in it becomes resources.cpu and resources.memory columns. That is the same flattener the JSON converters on this site use, so nesting behaves identically wherever you meet it.
A parser rather than a dependency
The TOML reader on this page is written by hand. That is a deliberate trade: a TOML library is around thirty kilobytes to read a config file with forty lines in it, and the whole point of these pages is that they load in a moment and run in your tab.
It covers TOML 1.0 as it appears in real files. Bare and quoted keys, dotted keys, [table] and [[array of tables]] headers with dotted names, inline tables, arrays, basic and literal strings including the triple-quoted multi-line forms, integers with underscore separators and the 0x, 0o and 0b prefixes, floats including inf and nan, booleans, and all four date-time forms.
The one piece people rely on that hand-written parsers usually miss is the line-ending backslash inside a multi-line string, which swallows the newline and the indentation after it. That is handled, because it is what makes a wrapped description in a config file readable in the first place.
Dates come through as the text that was in the file. TOML types them natively, but turning a Local Date into a date object and back would lose the distinction from an Offset Date-Time, and a CSV cell wants text regardless.
When the file is broken, you get the line number and what went wrong: a key defined twice, a value that could not be read, an unexpected character after a value. On a four-hundred-line file, an error without a line number is not an error message.
Questions
My file has several arrays of tables. Which one is used?
The top-level ones are preferred, and among those the one with the most entries. Never simply the first one found, which is how a converter picks up a three-entry tool.poetry.source block and ignores the four hundred rows below it. Every candidate is listed in the warnings with its entry count and its dotted path, and you can name a different one to switch.
What if my TOML has no repeated section at all?
It comes through as a single row with one column per dotted key, and a warning saying the file is not row shaped. That is the only honest reading of a plain config file, and it is genuinely what somebody converting a pyproject.toml or a Cargo.toml to a spreadsheet wants: every setting visible in one place.
Does this pull in a TOML library?
No. The parser is written by hand for this page, which is why it loads in a few kilobytes rather than shipping thirty to read a forty-line config file. It covers TOML 1.0: dotted keys, quoted keys, arrays of tables, inline tables, multi-line strings with the line-continuation backslash, integers with underscores and hex, octal and binary prefixes, floats including inf and nan, and all four date-time forms.
What happens to dates and times?
They come through as the text that was in the file. TOML types them natively, but converting them to a date object and back would lose the distinction between a Local Date and an Offset Date-Time, and a CSV cell wants text anyway. So 2024-11-03 stays 2024-11-03 and a timestamp keeps its offset exactly as written.
Are nested tables flattened?
Yes, with dot notation, using the same flattener the JSON converters use. A nested table inside each entry becomes columns such as resources.cpu and resources.memory. Nesting is followed four levels deep, and anything deeper or any array of tables inside an entry is kept as JSON text in its cell rather than being dropped.
What happens when the file is broken?
You get the line number and what went wrong: a key defined twice, a value that could not be read, an unexpected character after a value. A TOML error that does not say where is useless when the file is four hundred lines long, so the line is always reported.
Is anything uploaded?
No. Parsing runs in your browser tab with nothing sent to a server, nothing kept between visits and no row cap. Config files routinely carry hostnames, account ids and internal service names, which is a good reason to keep them local.
Related
Convert your TOML to CSV
No sign-up, no upload, no row cap. The right array picked, the alternatives named, errors with line numbers.
Back to the converter