JSON to CSV Converter

Which character separates one field from the next.
at key what was decided what came out
1:1 name top-level key · column 1 of 2 name
1:1 age top-level key · column 2 of 2 age
1:10 name of record 1 string Ada
1:22 age of record 1 number: the digits are written as they stand 36
1:34 name of record 2 string Grace
1:48 age of record 2 number: the digits are written as they stand 45

Nothing in this document was dropped or changed.

Going the other way? Convert CSV back to JSON

How do you convert JSON to CSV?

JSON to CSV reads a list and writes a table: each object in the array becomes one row, and each key becomes a column.

  1. Paste the JSON above. It has to be one object or an array of objects, because a row of a table is a record of fields.
  2. Collect every key that appears anywhere in the array, in the order the keys first appear. That set is the header row.
  3. Flatten a nested object into a dotted column name, so a name inside a user becomes the column user.name.
  4. Write one row per element, quoting a value only where it holds the delimiter, a quote or a line break, and leaving an empty cell where a key is missing.

This page writes CSV with one row per array element, nested objects flattened into dotted column names, and an empty cell where a key is missing.

JSON to CSV Conversion Table

A JSON document nests and a CSV file does not, so every shape has to land somewhere flat. This is where each one lands. objects and arrays, nested to any depth is the whole input side; none is the whole output side.

JSON to CSV Conversion Table
JSON shapeCSV columnCell value
"name": "Ada"nameAda
"age": 36age36
"active": trueactivetrue
"note": nullnote(empty)
"user": {"name": "Ada"}user.nameAda
"tags": ["x", "y"]tags.0 and tags.1x then y
the key is not in this objectthe column still exists(empty)

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 JSON and CSV Can Say
What it saysJSONCSV
SpecificationRFC 8259, Standards Track, December 2017; also ECMA-404RFC 4180, Informational, October 2005
Media typeapplication/jsontext/csv
Structureobjects and arrays, nested to any depthflat records of fields; no nesting
Delimitera comma (%x2C) between two members of an object and between two elements of an arraya comma (%x2C), fixed by the RFC 4180 grammar
Quotingdouble quotes; a quotation mark, a reverse solidus and the control characters U+0000 to U+001F must be escaped with a reverse solidusdouble quotes around the field; a double quote inside a quoted field is written twice
Header lineoptional; its presence is signalled by the text/csv header parameter, not by the file
Type setstring, number, boolean, null, object, arraynone - every field is text
Nestingunlimited by the grammar; a parser may set its own depth limitnone
Orderingan object is unordered; an array is ordered
Record separatorCRLF; the last record may omit it
Commentnone - the grammar has no comment productionnone defined
Spacesspaces are part of a field and are not ignored
EncodingUTF-8
StatusInformational; RFC 4180 records that no single master specification for the format exists

Worked Example: JSON to CSV

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 value that went in the cell.

JSON in
[{"name":"Ada","age":36},{"name":"Grace","age":45}]
CSV out
name,age
Ada,36
Grace,45
at key what was decided what came out
1:1 name top-level key · column 1 of 2 name
1:1 age top-level key · column 2 of 2 age
1:10 name of record 1 string Ada
1:22 age of record 1 number: the digits are written as they stand 36
1:34 name of record 2 string Grace
1:48 age of record 2 number: the digits are written as they stand 45

Result: the JSON above is the CSV beside it, and every decision that made it is listed below.

The keys were collected before a single row was written, which is why a record that is missing one still lines up with the rest. an object is unordered; an array is ordered — so the column order here is the order the keys first appear, not an order the document guarantees.

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 CSV file carries none - every field is text, so 36 and "36" reach the same cell and the reader at the other end has to decide again which one it was.

The document you paste in is read as UTF-8, and the table you copy out should be saved the same way. RFC 8259 requires JSON exchanged between systems to be encoded as UTF-8, and forbids adding a byte order mark to the front of a transmitted JSON text. A parser may ignore a byte order mark it finds rather than treat it as an error.

The delimiter above decides what the writer puts between two fields, and the choice is not free. A semicolon-separated or tab-separated file is not RFC 4180 CSV. The grammar fixes the separator at the comma (%x2C) and the media type has no delimiter parameter, so any other separator is read by convention rather than by the specification.

Check it in reverse

Read the table back and you get strings. Every cell arrives as text, because that is all a CSV file can hold, so the number 36 comes back as the string "36" unless you turn the type rule on at the other end. The column names come back as keys and a dotted name comes back as a flat key, not as the nested object it started as.

To prove nothing was lost, convert the CSV result back to JSON and compare it with the file you started from.

What This Conversion Cannot Carry

A CSV file is flat, single-typed and has no null, so a JSON document loses something on every one of those counts. 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.

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.
A repeated name in one object
The name "a" appears more than once in one object. RFC 8259 §4 says the names should be unique and records that software receiving a repeated name behaves unpredictably: some implementations keep the last pair, some fail, some keep all of them.

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 rows back in as JSON objects .

What Changes the CSV Output?

Which line ending the file uses

The output is written with CRLF between records. RFC 4180 is Informational and says plainly that no single master specification for CSV exists. The header line is optional and is signalled outside the file by the text/csv header parameter, and the document warns that some implementations use line endings other than CRLF.

Whether the objects carry the same keys

A record missing a key gets an empty cell rather than an invented value, and the converter says so. RFC 4180 fixes four things for CSV: each record sits on its own line ending in CRLF, fields are separated by commas, a field holding a comma, a double quote or a line break is wrapped in double quotes, and a double quote inside a quoted field is written twice.

The encoding you save it as

Save the result as UTF-8 and say so out of band, because the file will not say it for you. RFC 4180 carries the character set as an optional text/csv parameter and names US-ASCII as common usage. Nothing inside a CSV file records its encoding, so the encoding has to be known before the file is read.

JSON to CSV in Code

The same conversion in two lines, one per language. Both fix the column set before the first row is written. Neither line reports what the conversion could not carry; the converter above does.

Python: csv.DictWriter(out, fieldnames=cols, lineterminator="\r\n").writerows(rows)
JavaScript: rows.map(r => cols.map(c => quote(r[c])).join(",")).join("\r\n")

Common Mistakes

Frequently Asked Questions

What happens to nested objects?

They are flattened into dotted column names, so a name inside a user becomes the column user.name. A CSV file has no nesting, so the nesting is gone from the output.

What happens when the objects have different keys?

Every key that appears anywhere becomes a column, and a record with no value for one gets an empty cell. The converter reports each record that was missing a key.

When does a value need double quotes in the CSV?

When it holds the delimiter, a double quote or a line break. An empty string is quoted too, so that it can be told apart from an empty cell on the way back in.

Which line ending does the CSV use?

CRLF, which is what RFC 4180 fixes as the record separator. The last record may leave it off. Files written with LF are read back without complaint and reported.

Do JSON arrays become one cell or several rows?

Several columns. An array becomes one column per element, named tags.0, tags.1 and so on, and the array itself is gone. Only the top-level array becomes rows.

Yes. The same file converts straight back in the CSV to JSON direction .

Pick another pair from the format converter index.