ByteTips.

Guide

How to Convert JSON to CSV (Python, jq, and Online)

JSON converts cleanly to CSV when it is an array of flat objects — here is the Python, pandas, and jq for it, plus what to do with nested data.

October 17, 2026 · 6 min read · Shayan

Short answer: JSON converts cleanly to CSV when it is an array of flat objects — each object becomes a row, each key becomes a column. In Python it is ten lines with the csv module, and on the command line it is a single jq invocation. The only real work is nested data, which CSV cannot represent directly.

The shape that converts cleanly

CSV is two-dimensional: rows and columns, nothing else. The JSON shape that maps onto it without decisions is an array of objects with the same flat keys:

[
  { "id": 1, "name": "Alice", "role": "admin" },
  { "id": 2, "name": "Bob", "role": "editor" }
]
// becomes:
// id,name,role
// 1,Alice,admin
// 2,Bob,editor

Python: csv.DictWriter

For flat records, the standard library is all you need. This assumes the data is a list of dicts with uniform keys:

import json, csv

with open("data.json") as f:
    data = json.load(f)

with open("out.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=data[0].keys())
    writer.writeheader()
    writer.writerows(data)

Nested data: pandas json_normalize

When objects contain objects, flatten them first. json_normalize turns nested keys into dot-notation columns:

import pandas as pd

data = [
    {"id": 1, "user": {"name": "Alice", "city": "NYC"}},
    {"id": 2, "user": {"name": "Bob", "city": "SF"}},
]

df = pd.json_normalize(data, sep=".")
df.to_csv("out.csv", index=False)
# id,user.name,user.city
# 1,Alice,NYC
# 2,Bob,SF

The jq one-liner

On the command line, jq handles the whole job — headers included:

jq -r '(.[0] | keys_unsorted) as $k | $k, map([.[ $k[] ]])[] | @csv' data.json > out.csv

The traps

  • Nested objects don't fit: CSV has no nesting. Flatten with json_normalize first, or the converter joins the object into a single unreadable cell.
  • Non-uniform keys: if some records have fields others lack, collect every key across all records before writing — otherwise columns silently disappear.
  • Commas inside values: a value like "Boston, MA" must be quoted. DictWriter, pandas, and @csv all do this automatically; a hand-rolled string join does not.
  • Forgetting newline="" in Python: on Windows, the csv module without it writes a blank line after every row.
  • Excel showing one column: in some locales Excel expects semicolons, not commas. If everything lands in a single column, the delimiter is the problem — not your data.

Try it

Paste your JSON into the JSON / YAML / CSV — it converts in your browser with nothing uploaded, and shows you exactly how nested fields get flattened.

More guides