Local browser utility · Examples and limits included

JSON to CSV

Convert JSON into CSV in your browser, taking columns from every record rather than the first, flattening nested objects, and quoting fields correctly.

Columns are the union of every object’s keys, not just the first one’s, so a record that gains a field later still gets a column. Any value containing the delimiter, a quote or a line break is quoted automatically.

What the result contains

What This Tool Provides

Turn a JSON array of records into CSV a spreadsheet will open. Columns are taken from every object in the array rather than only the first, so a record that gained a field halfway through the export still gets a column. Nested objects are flattened into dotted names, and any value containing the delimiter, a quote or a line break is quoted the way RFC 4180 requires.

  • A header row naming every column found across all records
  • Nested objects flattened to dotted column names, or embedded as JSON
  • Correct quoting for values containing commas, quotes, or newlines
  • A per-record note wherever a field was missing or a value had no CSV form

How to Use This Tool

  1. Paste the JSONAn array of objects is the normal case. A single object is treated as a one-row table, and an array of arrays becomes rows without a header.
  2. Choose the shapePick a delimiter, decide whether to write a header row, and choose whether nested objects are flattened or embedded.
  3. Check the notes, then copyRecords missing a column are listed underneath. Copy the CSV when the report looks right.

How It Works

The JSON is parsed, then every record is walked to collect the union of its keys in first-seen order, which becomes the column list. Taking the first object as the schema would be faster and wrong: record sets where later entries carry extra fields are entirely ordinary, and those fields would vanish without warning. Each value is then rendered as text — strings as themselves, numbers and booleans by their literal form, null and undefined as empty — and passed through a quoting step that wraps a field in double quotes only when it contains the delimiter, a double quote, or a line break, doubling any internal quote as the specification requires.

Worked Examples

A comma inside a value

Input
[{"name": "Doe, Jane", "city": "Boston"}]
Output
name,city "Doe, Jane",Boston

The name is quoted because it contains the delimiter. The city is not, because it does not need to be — quoting everything is legal but harder to read.

Columns from every record, not just the first

Input
[{"a": 1}, {"a": 2, "b": 3}]
Output
a,b 1, 2,3 Item 1 has no value for b. Left empty.

The second record introduces column b. The first record simply has no value for it, which is reported rather than passed over.

A nested object flattened

Input
[{"user": {"name": "Jane", "city": "Boston"}}]
Output
user.name,user.city Jane,Boston

Dotted column names keep the structure legible in a spreadsheet. Turning flattening off embeds the object as JSON in a single user column instead.

JSON Has Shapes CSV Cannot Hold

The conversion is lossy in one direction and it is worth being precise about where. JSON is a tree; CSV is a rectangle. Anything in the tree that does not correspond to a cell has to be flattened, stringified, or dropped, and this tool never chooses the third option.

Nested objects are the common case and flattening handles them cleanly: a user object with name and city becomes user.name and user.city. Arrays are the harder case, because an array of tags has no fixed width and cannot become a fixed set of columns without inventing a convention. Those are written into the cell as JSON — a little ugly, entirely reversible, and better than either discarding them or exploding one record into several rows.

The deeper point is that a round trip through CSV is not identity. Convert JSON here, then convert the result back, and you get a flat table of strings and numbers: the nesting is now dotted names, the arrays are now JSON text in a cell, and the types have been re-inferred rather than remembered. That is fine when CSV is the destination and lossy when it is a transport format. If the system on the other end can accept JSON, send it JSON.

Getting the Quoting Right

Quoting is where most hand-written CSV writers fail, and the failure is silent. If a value containing a comma is written without quotes, the row gains a field, and every value after it shifts a column. Nothing errors; the file just means something different from what it says.

The rules are short. A field must be quoted if it contains the delimiter, a double quote, or a line break. Inside a quoted field, a literal double quote is written twice. Everything else may be written bare. This tool applies exactly those rules and quotes nothing else, which keeps the output readable rather than wrapping every cell in quotes as some exporters do.

The line-ending option matters more than it looks. RFC 4180 specifies CRLF, and some Windows tooling and older import routines genuinely require it; most modern tools, and anything in a Unix pipeline, are happier with plain LF. When an import silently produces one giant row, or leaves a stray character at the end of every line, the line endings are the first thing to check.

When a field gets quoted, and why
ValueWritten asReason
BostonBostonNothing needing an escape
Doe, JaneWrapped in double quotesContains the delimiter
She said "hi"Wrapped, with each internal quote doubledQuotes must be escaped by repetition
Two linesWrapped in double quotesContains a line break
nullAn empty fieldNull and undefined become empty
An array of tagsWrapped JSON textArrays have no cell form

What Happens to Types on the Way Out

CSV has no types at all — every field is text — so this direction of the conversion is the one that discards type information rather than guessing at it. A JSON number becomes its literal digits, a boolean becomes true or false, null becomes an empty field.

That last choice deserves an explanation, because the alternative is tempting. Writing the four characters n-u-l-l into the cell would preserve the distinction between null and empty string, and it would also mean a spreadsheet displays the word "null" in every gap, and that a later import reads it as ordinary text. An empty field is what a spreadsheet and every import routine treat as absent, so that is what gets written. The cost is that null and empty string are indistinguishable afterwards, which is worth knowing if that distinction carries meaning in your data.

The reverse trip re-guesses everything, and it guesses conservatively. A value with a leading zero comes back as a string rather than a number, precisely so a zip code survives; the same protection applies to integers too large to hold exactly. If types matter more than the tabular shape, keeping the data as JSON and formatting it preserves everything this conversion has to let go.

Where This Fits in a Real Task

The usual reason to convert in this direction is that a person needs to look at the data. An API returns JSON, and someone in finance or operations wants it in a spreadsheet. That is a completely legitimate use, and the flattening exists to make the result readable rather than technically faithful.

The second common reason is bulk import. Plenty of systems accept a CSV upload and nothing else, which makes this the last step of a pipeline rather than the middle of one. Before uploading, it is worth checking what you are about to hand over: exports of user records routinely carry an API key, a token, or a password column, and a spreadsheet is a far leakier container than a database. If you find a credential in the output, treat it as exposed and generate a replacement rather than re-importing it. A field that looks like meaningless noise is often Base64 rather than corruption, and decoding it will tell you which.

When something goes wrong after an import, the fastest diagnosis is usually comparison rather than inspection. Export the data back out, diff it against what you sent, and the row that changed will be obvious. If you only need a subset of a large export, testing a pattern against a sample first beats writing one against the whole file and hoping.

Important Edge Cases

  • A single JSON object rather than an array is treated as a one-row table, which is almost always what someone pasting one record intends.
  • An array of arrays is written as rows with no header, since there are no keys to name the columns.
  • Column order follows first appearance across the whole array, so a field introduced by a later record is appended rather than sorted in.
  • An empty object inside a record becomes a leaf column holding an empty value rather than disappearing during flattening.
  • A key containing a dot produces a column name indistinguishable from a flattened nested key, so a round trip through CSV cannot tell the two apart.

Limitations

  • The conversion is lossy: nesting becomes dotted names and arrays become JSON text, so a CSV round trip does not return the original structure.
  • Null and empty string are both written as an empty field and cannot be told apart afterwards.
  • There is no column selection, reordering, or renaming; every key found becomes a column.
  • Input is capped at 2,000,000 characters, so very large exports are better handled by a script.
  • Deeply nested records produce very wide tables, since every leaf becomes its own column.

Input handling

Private Browser Processing

The JSON you paste is parsed and converted entirely in your browser. Nothing is uploaded, stored, or logged, and no request is made while you convert — the network tab stays empty.

Google Analytics records page visits and whether a tool finished or failed, but these tool implementations do not send field values, generated passwords, QR payloads, uploaded QR images, or camera frames to analytics or a Tiny Tiny Tools processing endpoint.

See the Privacy Policy for site-wide details.

Questions About This Tool

What happens to nested objects?

They are flattened into dotted column names by default, so a user object becomes user.name and user.city. Turning flattening off embeds the whole object as JSON inside one column instead. Neither option discards anything.

Why are some fields quoted and others not?

A field is quoted only when it has to be: when it contains the delimiter, a double quote, or a line break. Quoting everything is legal but makes the file harder to read, so the tool applies the minimum the specification requires.

What if my records do not all have the same fields?

The columns are the union of every record’s keys, so nothing is lost. Records missing a column get an empty field and are listed underneath the output with the field they lacked.

Should I use CRLF or LF line endings?

RFC 4180 specifies CRLF and some Windows tooling requires it. Everything else is generally happier with LF, which is the default here. If an import produces one giant row, the line endings are the first thing to check.

Can I convert the CSV back to my original JSON?

You can convert it back to JSON, but not to the original structure. Nesting has become dotted column names, arrays have become JSON text in cells, and types are re-inferred rather than remembered. Use JSON end to end if the shape matters.

Is my JSON uploaded anywhere?

No. Parsing and conversion happen in your browser. There is no upload and no server copy, which you can confirm in the network tab.