From API response to spreadsheet
JSON is the native format of web APIs, but the people who need the data often live in spreadsheets. Typical cases: a list of orders pulled from a shop API that the accountant wants in Excel, user records exported from a NoSQL database for a quick pivot table, analytics events to filter in Google Sheets, or a batch of records to bulk-import into a CRM that accepts only CSV uploads. A CSV file is also the easiest format to diff, sort and grep on the command line.
The tool takes an array of objects and produces one row per object and one column per field, with a header row on top. A counter under the input shows how many rows were produced, which is a quick sanity check against the record count you expected.
How the table is built
Rows and columns are derived from the data itself, with no schema needed:
- Columns are the union of all keys, in the order they are first seen. If the first record has
idandname, and the tenth record also hasemail, the header ends withemailand the first nine rows leave that cell empty. - Nested objects are flattened with dots, so
{"customer": {"address": {"city": "Lyon"}}}produces a columncustomer.address.city. Any depth works. - A single object instead of an array is treated as a one-row table.
- Plain values in the array, such as
[1, 2, 3]or a list of strings, go into one column calledvalue. nullbecomes an empty cell, and booleans are written astrueandfalse.
An empty nested object such as "meta": {} has no fields to flatten, so it produces no column at all.
Arrays inside records
Spreadsheets have no notion of a list inside a cell, so an array such as "tags": ["red", "sale"] is written as its JSON text, ["red","sale"], in a single cell. That keeps the data lossless: you can parse it back later or split it with a spreadsheet formula.
If what you really need is one row per array element, for example one row per order line rather than per order, reshape the data first. In most scripting languages that is a one-line map over the parent records, copying the parent ID into each child. Feeding the reshaped array to the converter then gives a clean, fully tabular result.
Quoting and delimiters
A cell is wrapped in double quotes only when it has to be: when it contains the delimiter, a double quote, or a line break. Quotes inside a value are doubled, as RFC 4180 requires, so 6" pipe is written as "6"" pipe". Every other value is written bare, which keeps the file small and readable.
The delimiter matters most when the file is opened by double-clicking in Excel:
- Comma is the default for Google Sheets, LibreOffice, databases, Python's
csvmodule and almost every import tool. - Semicolon is what Excel expects when Windows is set to a locale that uses a comma as the decimal separator, which covers most of continental Europe and Latin America. With a comma file in those locales, every row lands in column A.
When in doubt, use the comma and open the file through Excel's Data, From Text/CSV import, which lets you pick the separator explicitly.
Getting it into Excel cleanly
A few problems happen after conversion, inside the spreadsheet, and are easy to prevent:
- Accented letters turn into symbols. The file is UTF-8 without a byte order mark, and some versions of Excel guess a legacy encoding when double-clicking it. Use the From Text/CSV import and choose UTF-8, or open the file in Google Sheets.
- Leading zeros and long IDs get mangled. Excel converts
00042to42and turns 16-digit or longer numbers into scientific notation. In the import dialog, set those columns to Text. - Dates change format. ISO strings like
2026-03-01T10:00:00Zmay be partially interpreted. Import the column as Text if you need the original value.
Note that numbers above 9,007,199,254,740,991 already lose precision when the JSON is parsed in the browser, so store very large IDs as strings in the source JSON if they must survive exactly.
Checking the input first
If the converter reports invalid JSON, paste the data into the JSON formatter, which shows the exact line and column of the problem. Data from a log file is often in JSON Lines format, one object per line with no surrounding brackets; wrap it in [ and ] and add commas between lines to make it a valid array. The reverse conversion is available as CSV to JSON. All processing happens in the page, so nothing you paste is sent anywhere.