How JSON rows become spreadsheet columns
A JSON to Excel converter reads an array of records and lays it out as a table: each object becomes a row, each distinct key becomes a column, and the first row holds the key names as headers. This tool writes the table to a real .xlsx workbook with a single sheet called "Sheet1", ready to download as data.xlsx.
The workbook is generated with SheetJS (the xlsx package, version 0.20.3) using its json_to_sheet utility, entirely in your browser. The file format is Office Open XML, standardised as ECMA-376, which Excel, LibreOffice Calc, Google Sheets and Numbers all open.
Example: records with uneven keys
Input:
[
{"name": "Ana", "age": 34, "active": true},
{"name": "Ben", "city": "Oslo", "age": null}
]
The sheet the converter produced, read back cell by cell:
| A | B | C | D | |
|---|---|---|---|---|
| 1 | name | age | active | city |
| 2 | Ana | 34 | TRUE | |
| 3 | Ben | Oslo |
city appears as column D because it was first seen in the second object. Ben's null age and missing active both produce empty cells. The 34 is a real number cell, and true is stored as a boolean, which Excel displays as TRUE.
Steps
- Paste a JSON array of objects into the input box.
- Click Convert. The output box fills with a long
data:URL; that's the encoded file, not something you need to read. - Click Download under the output to save
data.xlsx. - Open it in your spreadsheet app and rename the sheet or file as you like.
If your JSON fails to parse, the JSON validator will point to the broken spot faster than the converter's short error message.
Cell types and what to watch for
| JSON value | Cell written | Notes |
|---|---|---|
34, 42.5 |
Number | Sums and sorting work straight away |
true / false |
Boolean | Shows as TRUE / FALSE |
"Oslo" |
Text | |
"0012" |
Text | Leading zeros survive because it's a string |
"2026-10-27" |
Text | Not converted to an Excel date |
"=1+1" |
Text | Not evaluated as a formula |
null or missing key |
Empty cell | |
| nested object | One column per inner key | Named with a dot path, e.g. address.city |
array or {} |
Text | The value as JSON, e.g. ["a","b"] |
12345678901234567890 |
Number 12345678901234567000 |
Precision lost when the JSON is parsed |
Dates are the most common surprise. If you need real date cells for filtering, convert the column in Excel afterwards (Data > Text to Columns, or DATEVALUE). Long numeric IDs are the second: JavaScript numbers are exact only up to 2^53 - 1, and Excel itself keeps 15 significant digits (Excel specifications and limits). Send IDs as strings if every digit matters.
How nested data is flattened
Real API responses are rarely flat. Given [{"id":1,"address":{"city":"Lyon","geo":{"lat":45.76}},"tags":["a","b"]}], the converter writes these columns:
| id | address.city | address.geo.lat | tags |
|---|---|---|---|
| 1 | Lyon | 45.76 | ["a","b"] |
Nested objects are followed to any depth, and each leaf value gets its own column named by its path. Arrays stay in one cell as JSON text, because spreading them across rows or columns would change the shape of the table. If a key that already contains a dot collides with a nested path ("a.b" next to "a": {"b": ...}), the converter stops with an error naming the column instead of overwriting one value with the other.
If the rows you want are an inner array, extract it first. The JSONPath tester returns matches as a JSON array, so a path like $.data[*] gives you something you can paste straight in.
Every item in the array must be an object, since each one becomes a row. A mixed array such as [{"a":1}, 5, "x"] is rejected with "Item 2 of the array is a number, not an object", so you can find and fix the stray value.
Size limits
Excel sheets top out at 1,048,576 rows and 16,384 columns, and a cell holds at most 32,767 characters, according to Microsoft's specifications page linked above. Large inputs are also limited by your browser's memory, since the whole file is built in the page. For quick test data, the random JSON generator produces arrays of objects in the right shape, and the JSON formatter helps you check a big payload's structure before you convert it.
Last updated