Skip to main content

TSV to JSON: Paste From Excel and Get an Array of Objects

Convert tab-separated values to JSON in your browser. Paste straight from Excel or Sheets, the header row becomes keys, and each row turns into one object.

Published By Li Lei
#tsv #json #converter #spreadsheet #data

TSV to JSON: Paste From Excel and Get an Array of Objects

Every time I select a block of cells in a spreadsheet and copy it, the clipboard does not hand me a comma-separated string. It hands me tab-separated text. A tab sits between every column, a newline sits between every row, and that is TSV — the tab-delimited cousin of CSV. It is the single most common shape of structured data nobody talks about, because it is what comes out of Excel, Google Sheets, and Numbers the instant you press Ctrl+C.

The problem is that almost nothing downstream wants TSV. APIs want JSON. Seed scripts want JSON. Test fixtures want JSON. So the usual dance is: save the sheet as CSV, find a converter, hope it handles your delimiter, and clean up whatever it mangled. This post is about skipping all of that — pasting the tab-separated block directly and getting back a clean JSON array of objects, with the first row read as the keys.

What "header row becomes keys" actually means

Here is the one rule that makes the whole thing click: the first row becomes the keys, and each row after it becomes one object. The converter reads your top line as a list of field names, then walks down every following line and builds a JSON object where those names map to the cell values on that line.

So a three-column, three-row selection does not become a flat list of nine strings. It becomes an array of three objects, each carrying the same three keys. That structure — an array of objects sharing a key set — is exactly what JSON.parse gives you when you fetch a typical REST endpoint, which is why it drops into application code without reshaping.

If your data has no header row, flip the "first row is header" switch off. The tool then treats every line as data and names the columns col_1, col_2, col_3 left to right. That matters for raw log dumps or machine output that ships values with no labels — without the switch off, your first real record gets eaten as field names and you silently lose a row.

A worked example

Say I copied this out of a sheet (the gaps below are real tab characters):

name	age	active
Ada	36	true
Grace	41	false
Linus	29	true

With the header switch on, that becomes:

[
  { "name": "Ada", "age": "36", "active": "true" },
  { "name": "Grace", "age": "41", "active": "false" },
  { "name": "Linus", "age": "29", "active": "true" }
]

Notice that age and active came out as strings — "36", "true". By default every value stays text, which is the right call for IDs, phone numbers, and zip codes where a leading zero must survive. Turn on type inference and the same input gives you "age": 36 as a real number and "active": true as a real boolean, with empty cells and the literal word null becoming JSON null. Pick text for fidelity, inference for data you will do math on.

Why TSV beats CSV for messy text

People reach for CSV out of habit, but TSV quietly avoids CSV's worst failure. CSV separates columns with a comma, and real text is full of commas — a single cell holding Doe, John will split into two columns in a naive CSV parser and shear your whole table sideways. Tabs almost never appear inside ordinary prose, so TSV usually needs no quoting and no escaping at all. That is the same reason spreadsheets copy as tabs rather than commas in the first place.

When a field genuinely does contain a tab or a line break, TSV handles it the same way CSV does: wrap the field in double quotes. The parser follows RFC 4180 rules but with a tab as the delimiter, so "a\tb" is read as the single value a<tab>b instead of two columns, and a quoted field may span several physical lines. A literal double quote inside such a field is written as two double quotes. If your fields never contain tabs or newlines, you can ignore quoting entirely and just paste.

Everything stays in your browser

The parsing, the type inference, and the JSON pretty-printing all run as plain JavaScript inside your tab. Your pasted table never reaches a server, and nothing about it is logged. The one caveat worth knowing: the shareable link encodes your input into the URL's query string, so a link dropped into a chat will leave that data in the recipient server's access log. For anything sensitive, use the copy button and paste the JSON itself rather than sharing the URL.

That local-only design is also what makes this safe to hand to a non-technical teammate. Someone in ops who needs JSON but only knows Excel can open the TSV to JSON converter, paste their cells, and copy out the array — no terminal, no install, no upload, and no file ever leaves their machine.

Where this fits in a real workflow

I lean on this most when I am stitching a spreadsheet to an API. A colleague keeps a list of records in Sheets, an endpoint wants a JSON body, and instead of writing a one-off import script I select the range, paste, leave the header on, and the column titles land as object keys. The whole round trip is two keystrokes and a copy.

It is just as handy for seeding. Hand me a tab-separated dump of sample rows, turn inference on so the numeric and boolean columns arrive as real numbers and booleans, and I have a JSON array ready to import into a seed script or save as a fixtures file my tests load. For headerless log lines, the switch goes off, the fields come out as col_1, col_2, col_3, and the JSON pipes straight into whatever expects structured records — with the raw values kept as strings, which is safer for IDs and timestamps.

A couple of mistakes are worth naming so you avoid them. First, do not paste comma-separated text and expect columns — this tool splits on tabs, because that is what spreadsheets copy. If your data uses commas it is CSV, and you want the CSV to JSON converter instead. Second, do not leave type inference on for IDs with leading zeros: 00042 will read as the number 42 and the zeros vanish, so turn inference off for any value where the digits are an identifier, not a quantity.

That is the entire model. Tabs in, an array of objects out, headers as keys, and a single switch each for headers and types. Once you internalize "first row becomes keys, every other row becomes an object," pasting straight from a spreadsheet stops being a chore and becomes the fastest path you have to structured data.


Made by Toolora · Updated 2026-06-13