The fastest path from a spreadsheet to JSON
When you select cells in Excel, Google Sheets, LibreOffice or Numbers and press copy, the clipboard holds tab-separated values. That makes TSV the quickest route from a spreadsheet to JSON: no export dialog, no file, just copy and paste. TSV is also the native output of many command-line tools (mysql -B, cut, BigQuery’s console) and the format of bioinformatics and linguistics datasets.
Because tabs almost never occur inside real values, TSV avoids most of CSV’s quoting problems, which makes it a reliable intermediate format.
How tabs, quotes and line breaks are treated
Each line is a row and each tab starts a new field. Commas, semicolons and quotes inside values are ordinary characters, so Tan, Aisha is one field.
Plain TSV has no quoting rules, but spreadsheets do quote a cell when it contains a tab or a line break. The converter therefore reads TSV quote-aware: a field that starts and ends with " is unquoted, with "" becoming one quote. If the quotes in the input are not balanced — say a value like 5" screen — it falls back to treating every quote literally and adds an info message, so the data still converts instead of failing.
Blank lines are skipped, and any mix of CRLF and LF line endings is accepted.
Header row and ragged rows
First row is a header (on by default) turns the first row into keys and every later row into an object. Turn it off and you get an array of arrays, one inner array per row.
Spreadsheet selections are often uneven. When a row has fewer fields than the header, the missing keys are set to null; when it has more, the extra values are kept under column_4, column_5 and so on. Empty header cells become column_N, and duplicate headers get a numeric suffix (total_2). Each repair is listed as a warning with its line number.
Type detection
Detect numbers, booleans and empty values (on by default) converts empty cells to null, the exact words true and false to booleans, and plain decimal numbers to JSON numbers while keeping their spelling. Values that would change if converted stay strings: leading zeros (007), a leading plus (+44), exponent notation, -0, and integers beyond 2^53. Spreadsheets display TRUE in capitals, which is kept as the string "TRUE".
Turn detection off to keep every value exactly as copied, with empty cells as empty strings. That is the safer choice for identifier-heavy sheets.
Related tools
For comma-separated files use CSV to JSON, which applies the same typing rules. To change the delimiter without touching the data, use TSV to CSV. Neither tool, nor this one, uploads what you paste.
Examples
Range copied from a spreadsheet
The comma in “Tan, Aisha” needs no quoting in TSV, and the balances become numbers with their written decimals.
id name city joined balance
1 Tan, Aisha Singapore 2024-03-11 1520.50
2 Ben Okafor Lagos 2023-11-02 88.00
3 Chloé Martin Paris 2025-01-20 -12.75
[
{
"id": 1,
"name": "Tan, Aisha",
"city": "Singapore",
"joined": "2024-03-11",
"balance": 1520.50
},
{
"id": 2,
"name": "Ben Okafor",
"city": "Lagos",
"joined": "2023-11-02",
"balance": 88.00
},
{
"id": 3,
"name": "Chloé Martin",
"city": "Paris",
"joined": "2025-01-20",
"balance": -12.75
}
]
Uneven rows and literal quotes
The inch mark is kept as a literal quote, the short row gets a null price and the extra field lands in column_4.
product size price
Monitor 27" 4K 349.00
Cable 2m
Dock USB-C 129.00 clearance
[
{
"product": "Monitor",
"size": "27\" 4K",
"price": 349.00
},
{
"product": "Cable",
"size": "2m",
"price": null
},
{
"product": "Dock",
"size": "USB-C",
"price": 129.00,
"column_4": "clearance"
}
]
Keep everything as text
With detection off, account numbers and dates are left exactly as copied.
account sort_code opened
00012345 20-00-00 2019-07-01
00098765 40-11-62 2021-02-15
[
{
"account": "00012345",
"sort_code": "20-00-00",
"opened": "2019-07-01"
},
{
"account": "00098765",
"sort_code": "40-11-62",
"opened": "2021-02-15"
}
]
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Quotes are not balanced, so they were kept as literal text | An info note: a quote character in the data does not form a properly quoted field. | Usually nothing to fix; check that values containing " came through as you expect. |
Row has 3 fields, expected 2; the extra fields are kept in additional columnsExplained | A row contains an extra tab, often a trailing tab copied from an adjacent empty cell. | Remove stray tabs, or keep the generated column_N key. |
Column 3 has no header; named it "column_3" | The header row has an empty cell, for example a blank spreadsheet column inside the selection. | Type a header into the empty cell before copying, or rename the key afterwards. |
Frequently asked questions
Can I paste directly from Excel or Google Sheets?
Yes. Copied cells are tab-separated, which is exactly what this converter reads. Include the header row in your selection.
What if a value contains a double quote?
It is kept. Quotes only have special meaning when a field starts and ends with them; unbalanced quotes are treated as plain text.
Why is TRUE from my spreadsheet still a string?
Only lower-case true and false become booleans, to avoid surprising conversions. Replace the values or post-process the JSON if you need booleans.
How are empty cells converted?
To null with type detection on, or to an empty string with it off.