Excel to JSON Converter

Drop an XLSX, XLS or XLSM file and the rows come back as JSON. Choose the array shape or one object per line, indented or compact, and an identifier that starts with a zero keeps it. Your browser does the work, so the workbook never leaves the machine and there is no queue to sit in.

Want to drop columns or filter rows on the way through? Open the app

Why a sheet ends up as JSON

Spreadsheets are where data gets edited. JSON is where data gets consumed. Almost every conversion in this direction is somebody closing that gap:

  • Fixtures a frontend can render against. QA keeps 200 sample accounts in a shared workbook because editing them there takes seconds. The interface needs an array of objects to import while the real endpoint is still being built.
  • Reference data somebody else owns. Pricing tiers, shipping zones, tax bands, feature flags. Ops edits the sheet; the service reads JSON at boot.
  • Loading a document store. Firestore, MongoDB and Elasticsearch all ingest JSON documents. None of them will look at a workbook.
  • Training and eval sets for language models. A reviewer can edit prompts and expected answers in a sheet without going near a repository. Switch Structure to JSON Lines and the download is a .jsonl that fine-tuning pipelines read without a preprocessing script in front of it.
  • Anything that has to go in a request body. A Postman check, a webhook fixture, a payload pasted into a bug report. JSON drops straight in where a spreadsheet attachment starts a conversation.

Worked example: four signups and one leading zero

A trial signup sheet, four rows. The zip column was formatted as text in Excel, one seats cell was left blank, and the started column holds real date cells displayed in yyyy-mm-dd:

name zip plan seats started
Nadia Okoro 02138 pro 12 2025-11-03
Sam Ellery 94110 free 1 2026-01-20
Priya Raman 07030 pro 2025-08-14
Tom Vasquez 60614 team 25 2026-02-01

Dropped into the box above with nothing changed, that sheet comes back as:

[
  {
    "name": "Nadia Okoro",
    "zip": "02138",
    "plan": "pro",
    "seats": 12,
    "started": "2025-11-03"
  },
  {
    "name": "Sam Ellery",
    "zip": 94110,
    "plan": "free",
    "seats": 1,
    "started": "2026-01-20"
  },
  {
    "name": "Priya Raman",
    "zip": "07030",
    "plan": "pro",
    "seats": null,
    "started": "2025-08-14"
  },
  {
    "name": "Tom Vasquez",
    "zip": 60614,
    "plan": "team",
    "seats": 25,
    "started": "2026-02-01"
  }
]

Four decisions are visible there. Both ZIP codes with a leading zero kept their quotes, because a number would print them back one digit short. The other two had no zero to protect and were typed as numbers, which is the honest edge of the rule rather than a bug. Priya's blank seats cell became null, not 0 and not an empty string. And the dates arrived as the text the sheet displays, not the five-digit serial numbers Excel stores underneath.

Switch Structure to JSON Lines and the same four rows come back like this, downloaded as signups.jsonl:

{"name":"Nadia Okoro","zip":"02138","plan":"pro","seats":12,"started":"2025-11-03"}
{"name":"Sam Ellery","zip":94110,"plan":"free","seats":1,"started":"2026-01-20"}
{"name":"Priya Raman","zip":"07030","plan":"pro","seats":null,"started":"2025-08-14"}
{"name":"Tom Vasquez","zip":60614,"plan":"team","seats":25,"started":"2026-02-01"}

Minified is the third shape: one array, no indentation, one long line. Same data as the pretty output, about a third smaller, and the right pick when the destination is a request body.

Which sheet you get

Real workbooks have tabs. The signup file above also carried a sheet called Notes, and stopping for a dialog before showing any output would have been the wrong trade.

So the leftmost sheet is converted the moment the file lands, and every sheet name is listed in a Sheet dropdown next to the Formatting and Structure controls, with the one that was used already selected. Pick a different name and the conversion re-runs against it in place. Nothing is stitched together across tabs: one run reads one sheet and produces one JSON document, so three sheets as three files means three runs with the dropdown moved between them.

How a cell becomes a JSON value

Excel cells carry a stored value and a display format. Which of the two you get is the difference between usable output and a support ticket, so the rules here are narrow on purpose:

  • What the cell shows is what gets converted. The number 2215 under a 00000 custom format reaches the JSON as "02215". A 0.125 shown as a percentage arrives as "12.5%", and 1240.5 under a currency format as "$1,240.50".
  • Typing survives only a clean round trip. A value is a number only if turning that number back into text gives every original character back. 12 and 41.5 qualify. 02138 does not, nor does a 17-digit order reference that would lose its last digits to floating point.
  • Empty means null. A blank cell becomes null, so a consumer can tell an unanswered field from a deliberate zero.
  • Formulas hand over their results. Excel saves the last computed value alongside the formula, and that value is what gets read. A cell holding =C2*2 shows up as 96, and the formula text appears nowhere.
  • TRUE and FALSE stay strings. Excel writes booleans in capitals, and only the lowercase spellings become real JSON booleans, so a checkbox column arrives as "TRUE" and "FALSE". Map them in code, or add a helper column with lowercase text.
  • Error cells carry their error across. A cell displaying #DIV/0! lands in the JSON as that string rather than crashing the run or turning into null. Broken formulas stay visible, which is where you want them.

Gotchas worth knowing before you convert

  • Date output follows the cell format. The same day gives "2025-11-03" from a yyyy-mm-dd column, "11/3/25" from an m/d/yy one, and "03-Nov-2025" from dd-mmm-yyyy. A date cell still on General has no date formatting to read and surfaces as the raw serial number 45964. Set the format first and you choose the output.
  • Merged cells fill only their first row. A region label merged down three rows gives one value and two null entries, because only the top-left cell of a merge holds anything. Unmerge and fill down if every record needs the label.
  • Row one is the header row, no exceptions. A title banner above the table becomes your key names, so delete it first. Two columns both named id collapse into one key holding the right-most value, and a blank header cell produces a generated name such as column_3.
  • Blank rows are dropped. A spacer row in the middle of a report does not become an empty object, so the record count matches what a human would count.
  • There is no paste box on this page. A workbook is a zip archive of XML, so it has to arrive as a file. If what you have is cells on the clipboard, our CSV to JSON converter reads the tab-separated text a spreadsheet copy produces.
  • The limit on this page is 100 MB. No row cap and no daily allowance, but a workbook is unpacked whole rather than streamed, so a dense file well under that limit can still exhaust the tab's memory. Anything bigger goes to the full editor.

Frequently Asked Questions

Is my workbook uploaded to a server?

No. The spreadsheet is unpacked and converted by JavaScript inside your tab, and this page has no upload endpoint to send it to. Close the tab and the data is gone with it.

My workbook has several sheets. Which one gets converted?

The first one, straight away, with no dialog in front of it. Every sheet name in the file then appears in a Sheet dropdown beside the output controls, with the converted one already selected. Choose another name and the conversion runs again against that sheet. Sheets are never merged, so one run produces one JSON document.

What do date cells turn into?

The text the cell displays. A date formatted as yyyy-mm-dd arrives as 2025-11-03, and the same underlying date formatted as m/d/yy arrives as 11/3/25. A date cell still on the General format has no date formatting to read, so it comes through as Excel's raw serial number instead. Set the column format before converting and you decide the shape.

Why did one ZIP code stay quoted while another became a number?

A run of digits is typed as a JSON number only if converting it back to text reproduces the original characters. 02138 would come back as 2138, so it keeps its quotes. 94110 passes that test and lands as a number. A leading zero is the only clue available that a run of digits is a label rather than a quantity.

When is JSON Lines the better choice?

Whenever the reader on the other end takes one record at a time: log shippers, BigQuery and Snowflake loads, and the training and eval files that language model tooling expects. Switch Structure to JSON Lines and the download is named .jsonl. Keep the array when a single JSON.parse has to swallow the whole thing.

Does it open .xls and .xlsm files, and how large can they be?

Yes to both older .xls workbooks and macro-enabled .xlsm files; macros are ignored and only the cell values are read. The ceiling on this page is 100 MB. A spreadsheet is unpacked whole rather than streamed, so a dense workbook well under that limit can still be the point where your browser runs short of memory.

Turn your spreadsheet into JSON

No account, no upload, no row cap. Pick the sheet, pick the shape, copy the result or take the file.

Back to the converter