JSON Viewer

How to turn JSON into CSV

The rules for flattening nested data into columns, the traps, and three ways to do it.

Updated 2026-11-04 · 6 minute read

CSV holds rows and columns. JSON holds a tree. Turning one into the other always means a decision about what to do with the parts that do not fit. This page says what those decisions are, so you can choose them instead of discovering them later.

What converts cleanly

A list of flat objects:

[
  {"id": 1, "name": "Ada", "active": true},
  {"id": 2, "name": "Grace", "active": false}
]

becomes

id,name,active
1,Ada,true
2,Grace,false

One row for each object. One column for each key. That is the whole idea.

The four decisions

1. Which list?

CSV needs a list of records. A real API answer usually wraps it:

{
  "total": 2,
  "page": 1,
  "results": [ { "id": 1 }, { "id": 2 } ]
}

The rows are in results. The tool must find it, and must tell you which list it chose. This viewer uses the first list it finds and says so in a message, so you can check.

2. What about nested objects?

{"user": {"name": "Ada", "city": "London"}}

The usual answer is to flatten with a dotted name:

user.name,user.city
Ada,London

This viewer does that, at any depth.

3. What about a list inside a record?

{"id": 1, "tags": ["a", "b"]}

There are three answers, and none is right for every case:

Answer Result Good for
Keep the JSON text "[""a"",""b""]" Keeping all the data
Join with a separator a|b Reading by eye
One row for each item two rows for id 1 Counting and grouping

This viewer keeps the JSON text, because that loses nothing. If you need one row for each item, do that step first with jq.

4. What if the records have different keys?

[{"a": 1}, {"b": 2}]

Every column must exist on every row, so the answer is a union of all the keys, with an empty cell where a record has none:

a,b
1,
,2

A tool that only reads the first record will silently drop the b column. This viewer reads the first 500 records to build the columns, and says so when the list is longer.

The escaping rules

These are the rules that break a spreadsheet when a tool gets them wrong.

a,b,c
"x,y","he said ""no""","one
two"

That is one row with three cells, and the third cell holds a line break.

Three ways to do it

In this viewer

Open the file, then Tools → To CSV. A window shows the result with Copy and Download. It flattens nested objects, fills missing cells and escapes correctly. Because the work happens in the browser, the file never leaves your machine, and a list of a million records still converts.

With jq

Full control, and good for a repeated job:

# pick the columns yourself
jq -r '["id","name"], (.results[] | [.id, .name]) | @csv' data.json > out.csv

# every key of the first record, as the header
jq -r '(.results[0] | keys_unsorted) as $cols
       | $cols, (.results[] | [.[$cols[]]])
       | @csv' data.json > out.csv

@csv handles the quotation marks for you. Use -r so the output is raw text.

In Python

import csv, json

with open('data.json') as f:
    rows = json.load(f)['results']

columns = []
for row in rows:
    for key in row:
        if key not in columns:
            columns.append(key)

with open('out.csv', 'w', newline='') as f:
    writer = csv.DictWriter(f, fieldnames=columns, extrasaction='ignore')
    writer.writeheader()
    writer.writerows(rows)

newline='' matters. Without it, Python writes an extra blank line between rows on Windows.

Traps worth knowing

A spreadsheet changes your data. Excel turns 00123 into 123, and it turns 1-2 into a date. This is not a fault in your CSV. If the identifiers matter, import the file rather than opening it, and set the column type to text.

A big number loses digits. An identifier with 18 digits goes through most tools as a floating point number and comes out changed. See big numbers in JSON. This viewer never turns the text into a number, so the digits survive the conversion.

UTF-8 and Excel. Older versions of Excel need a byte-order mark to read UTF-8 text. If the accents come out wrong, that is why.

null against empty. A null becomes an empty cell, and so does a key that was missing. CSV cannot tell the two apart. If that difference matters, CSV is the wrong format.

Try it on your own file. The tool runs in your browser. Nothing is uploaded, and nothing is stored on a server.

Open the JSON Viewer

Read next

How to turn JSON into a TypeScript interface

Get types from a real API answer in seconds, and know what the generated types cannot tell you.

JSON Schema — check your data before it breaks something

Write a schema that catches bad data, with the keywords that matter and the traps that waste a day.