From an API response to something a colleague can filter
JSON is the format machines agree on. Spreadsheets are the format people agree on. The gap between the two is where this tool lives: an export of orders, a dump of survey answers, a list of users pulled from an admin API, a fixture file somebody needs to review. All of it is perfectly readable to the person who wrote the endpoint and completely opaque to the manager who has to sign off on it.
The usual answers are worse than they look. A one-off script means installing something, writing it, and rewriting it the next time the shape of the export changes. Pasting JSON into a spreadsheet gives you one long column of braces. Copying it through an online converter means handing over data that often contains customer names, internal IDs or an access token that somebody left in a debug response.
What flattening does to a record
Excel wants a rectangle. JSON does not have to be one. So before anything is written, every record is flattened: a nested object becomes dot-notation columns, and this happens all the way down. Given a record where user contains address which contains city, you get a column headed user.address.city. A null stays a value in its own cell and is not descended into, which matters more than it sounds, because in JavaScript null reports its type as an object and a naive flattener crashes or loses the field entirely.
Arrays are treated differently on purpose. A field holding ["admin","user"] stays in one cell, written as that JSON text. The alternative, spreading it across numbered columns, would make your column set depend on whichever record happens to have the longest array, so a 900-row export would grow a tags.7 column because of one outlier. Keeping it as text means the column list is predictable and the original value is always recoverable with a JSON.parse on the cell.
The silent data loss that shaped this converter
Worth being specific about, because it is the reason the code has an extra step. The conversion is built on SheetJS (the open-source xlsx package), whose json_to_sheet helper turns an array of plain objects into a worksheet. Hand it a cell value that is still a raw JavaScript array or a raw nested object and it does not write an ugly placeholder string, which is what you would expect. We wrote the workbook to a real .xlsx buffer and read it back: the cell came out empty. Not wrong, not ugly, just gone.
That is the worst possible failure for a data conversion, because the sheet looks finished. So the pipeline runs in two passes: flatten every nested object into dot columns, then stringify anything array-shaped that is left, and only then hand the rows over. The test suite pins both behaviours, along with two more oddities we found in the same library. Passing it an array of strings makes it treat each string as an object and explode it into one column per character. Passing it an array of numbers silently produces zero rows, because a number has no enumerable keys. Both are handled by wrapping any non-object element into a single value column first, so ["a","b","c"] becomes a sensible one-column sheet instead of alphabet soup.
Converting a file
- Drop one or more
.jsonfiles into the box above, or click Choose files. - Click Convert JSON to Excel. Parsing, flattening and workbook generation all happen in the tab you are reading this in.
- Download each
.xlsxand open it in Excel, Google Sheets, Numbers or LibreOffice Calc.
If a file is not valid JSON, the error names the file, so you know which one to fix in a batch of six. Reformatting it in the JSON Formatter first will usually show you the trailing comma or unquoted key that broke it.
Why the workbook is assembled inside the tab
There is no upload step here, and that is a design constraint rather than a feature we bolted on. The xlsx library is loaded into your browser on demand, your file is read with the browser’s own file reader, and the finished workbook is assembled as a byte array in the tab’s memory and handed straight to your downloads folder. No copy of it exists anywhere else, and once the page has loaded you can disconnect from the network and the conversion still works.
This matters for the specific kind of file people convert. JSON exports are what you get out of admin panels and internal APIs, which means they routinely carry email addresses, order histories, internal user IDs and the occasional bearer token nobody remembered to strip. Those should not pass through a stranger’s server just to become a spreadsheet.
Excel, CSV, or back the other way
Reach for .xlsx when the file is for a person: it keeps a single named sheet, opens without an import dialog, and cannot be mangled by a locale that expects semicolons instead of commas. Reach for Convert JSON to CSV when the file is for a machine, since CSV is smaller, diffs cleanly in Git and imports into almost any database loader. The two tools deliberately share the same flattening logic, so the columns come out identical either way.
If you are going the opposite direction, Convert Excel to JSON completes the round trip, and CSV to SQL turns tabular data straight into INSERT statements. One thing none of them do is formatting: the output here is data only, with no column widths, cell styles, frozen headers or formulas, so a sheet meant for presentation still needs five minutes of work once it opens.

