JSON to TSV Converter
Nothing in this document was dropped or changed.
Going the other way? Convert TSV back to JSON →
How do you convert JSON to TSV?
JSON to TSV writes one name line and then one tab-separated row per element of the array, with the nested keys flattened first.
- Paste the JSON above. It has to be one object or an array of objects.
- Flatten the nested keys into dotted names and collect one column set for the whole file, because every record has to carry the same number of fields.
- Replace any tab or line break inside a value, since a tab-separated file has no way to quote one.
- Write the name line, then one tab-separated row per element, with an empty field where a key is missing.
This page writes tab-separated rows behind one name line, nested keys flattened, and a declared replacement for any tab character inside a value.
JSON to TSV Conversion Table
Every JSON shape has to land in a flat field, and a tab-separated field is flatter than most: it cannot hold a tab and it cannot hold a line break. none nesting, and none - a field containing a tab is not allowable.
| JSON shape | TSV column | Field value |
|---|---|---|
| "name": "Ada" | name | Ada |
| "age": 36 | age | 36 |
| "active": true | active | true |
| "note": null | note | (empty) |
| "user": {"name": "Ada"} | user.name | Ada |
| "tags": ["x", "y"] | tags.0 and tags.1 | x then y |
| a value holding a tab | unchanged | the tab replaced by a space |
A format is defined by what it can say. The rows below put the two halves of this conversion side by side, so the gap the conversion has to cross is a thing you can read rather than a thing you find out later. Every value in the table is the wording the defining document uses, not a summary of it, and a dash means the format has no answer to that row at all.
| What it says | JSON | TSV |
|---|---|---|
| Specification | RFC 8259, Standards Track, December 2017; also ECMA-404 | IANA media type registration for text/tab-separated-values; no RFC and no standards-body document |
| Media type | application/json | text/tab-separated-values |
| Structure | objects and arrays, nested to any depth | flat records of fields; no nesting |
| Delimiter | a comma (%x2C) between two members of an object and between two elements of an array | a tab character |
| Quoting | double quotes; a quotation mark, a reverse solidus and the control characters U+0000 to U+001F must be escaped with a reverse solidus | none - a field containing a tab is not allowable |
| Header line | — | required - the first line holds the field names |
| Field count | — | every record must carry the same number of fields |
| Type set | string, number, boolean, null, object, array | none - every field is text |
| Nesting | unlimited by the grammar; a parser may set its own depth limit | none |
| Ordering | an object is unordered; an array is ordered | — |
| Comment | none - the grammar has no comment production | — |
| Encoding | UTF-8 | — |
Worked Example: JSON to TSV
An array of two objects, converted here at build time by the same code the box above runs. The working under it names each key, the column it became and the field that was written, so you can see the column set being fixed before a single row exists rather than emerging halfway down the file.
[{"name":"Ada","age":36},{"name":"Grace","age":45}] name age
Ada 36
Grace 45 Result: the JSON above is the TSV beside it, and every decision that made it is listed below.
One column set was fixed before any row was written, and on this file that is invisible because both records carry the same keys. The IANA registration for TSV requires every record to have the same number of fields, so a JSON array whose objects carry different keys cannot be written as TSV until one column set is fixed for the whole file.
The types went in and did not come out. RFC 8259 gives JSON four primitive types - string, number, boolean and null - and two structured types, object and array. There is no date type and no separate integer type, so a date arrives as a string and every number is read the same way. A tab-separated file carries none - every field is text, so the reader at the other end has to decide again.
Check it in reverse
Reading the rows back gives you the same records with every value as a string, because that is all a tab-separated field can hold. A dotted column name comes back as a flat key rather than as the object it was flattened from, and a field that had a tab replaced in it comes back with the replacement, not the tab. Everything else survives, and the name line is what makes that possible: it is the one record of which column held which key.
To prove nothing was lost, convert the TSV result back to JSON and compare it with the file you started from.
What This Conversion Cannot Carry
A tab-separated file is the strictest shape in this family: flat, untyped, and with no way to escape its own delimiter. A JSON number is written in base 10, leading zeros are not allowed, and Infinity and NaN are not permitted. RFC 8259 lets a parser set its own limits on range and precision, so integers outside -(2^53)+1 to (2^53)-1 are where two parsers start to disagree about the same file.
- A tab or a line break inside a value
- A value held a tab or a line break. TSV has no quoting mechanism — the IANA registration for text/tab-separated-values says such a field is not allowable — so each one was replaced with " " and the original character is gone.
- An array inside a record
- An array was flattened into one column per element — tags.0, tags.1 and so on. A delimited file has no nesting (FMT-csv-nesting), so the array is gone and only its elements remain.
- A key one record does not have
- A record was missing a key another record has, so its cell was left empty. OUTCONV-json-to-csv: an empty cell where a key is missing — which is also what a JSON null writes, so the file cannot tell the two apart.
- An empty object or array
- An empty object became an empty cell. A delimited file has no way to write "an object with no members" (FMT-csv-nesting).
- A very large integer
- The integer 12345678901234567890 lies outside -(2^53)+1 to (2^53)-1. RFC 8259 §6 lets a parser set its own limits on range and precision, so this is where two parsers start to disagree about the same file. The digits were carried through unchanged.
Each line above is written by the converter itself, and it appears under your own result whenever your document raises it. Nothing is dropped without one.
The sample above reverses exactly - read the same tab-separated rows back in as JSON .
What Has To Be Fixed Before a Tab-Separated File Is Written?
Whether a value holds a tab or a line break
Either one is replaced before the file is written, and the replacement is declared rather than silent. TSV has no quoting mechanism. The IANA registration for text/tab-separated-values states that fields containing tabs are not allowable, so a tab inside a value cannot be escaped - it has to be removed or replaced before the file is written.
Whether the records carry the same keys
They have to, so one column set is fixed for the whole file first. A TSV file's first line is the field names, and the IANA registration puts that line in the grammar as tsv ::= nameline record+. Where CSV's header row is optional, a TSV file without a name line is not TSV.
What order the columns come out in
The order the keys first appear in the document. an object is unordered; an array is ordered, so a JSON object gives no order to follow and the converter has to choose one and say so.
JSON to TSV in Code
The same conversion in two lines, one per language. Both need the column set before the first row, and neither escapes a tab. Neither line reports what the conversion could not carry; the converter above does.
Python: "\r\n".join("\t".join(str(r.get(c, "")) for c in cols) for r in rows) JavaScript: rows.map(r => cols.map(c => String(r[c] ?? "")).join("\t")).join("\r\n") Common Mistakes
- Leaving a tab inside a value. The record then carries one field too many and the file stops lining up from that row onward.
- Assuming the columns come out in the order the keys are written. An object is unordered, so the name line is the only record of the order.
- Reading an empty field as a null. A missing key and a JSON null both write nothing, so the file cannot tell you which one it was.
Frequently Asked Questions
Why does every record need the same number of fields?
Because the registration for text/tab-separated-values requires it. One column set is fixed for the whole file first, so a record missing a key gets an empty field rather than a short row.
What happens if a value contains a tab?
It is replaced, and the converter says so. There is no quoting mechanism in a tab-separated file, so a field holding a tab is not allowable and the original character is gone.
Why paste TSV into a spreadsheet rather than CSV?
Because a tab pastes straight into columns while a comma usually opens an import dialog. The trade is that a value holding a tab cannot be written at all.
Yes. The same file converts straight back in the TSV to JSON direction .
Related Conversions
The rest of the family sits on the data format converters.