JSON to CSV Conversion Guide for Beginners

How to convert JSON to CSV with a converter or code: flattening nested data, escaping commas, and validating the result.

Converting JSON to CSV looks trivial and quietly eats an afternoon. JSON is nested; CSV is flat. The moment your data has an object inside an object, someone has to decide how to flatten it — and that decision is where most conversions go wrong. Here’s the practical version, with real examples.

Why JSON and CSV don’t line up

JSON can hold anything: objects, arrays, arrays of objects, null, numbers, booleans.

{
  "name": "Ada",
  "age": 30,
  "address": { "city": "New York", "zip": "10001" },
  "skills": ["math", "code"]
}

CSV is a flat grid. One line per record, one value per column:

name,age,city,zip,skills
Ada,30,New York,10001,math; code

Every CSV conversion is really two decisions:

  1. What’s a column? name, age, and city are obvious. address.city and address.zip had to be flattened into their own columns.
  2. What’s a cell? skills is an array — CSV has no native list type, so it becomes one cell (usually joined with a separator) or gets dropped.

There’s no universally correct answer to either. That’s why “just convert it” fails: the tool guesses, and you discover the guess on row 50,000.

Method 1: a JSON to CSV converter

For a one-off conversion, an online converter is the fastest path. The JSON Converter on this site converts JSON to CSV in your browser — nothing is uploaded, which matters if the payload is real data.

The workflow:

  1. Validate first. A JSON-to-CSV converter fails on invalid JSON with a confusing error. Validate the input with a JSON validator first — it tells you the exact line and column of the problem.
  2. Paste and convert. Paste the JSON, pick CSV, hit Convert.
  3. Review the headers. Make sure nested fields flattened the way you expected.

Method 2: convert with code

If you need repeatable conversions, code wins. A minimal JavaScript example:

const rows = data.map((row) => ({
  name: row.name,
  age: row.age,
  city: row.address?.city,
  zip: row.address?.zip,
  skills: (row.skills || []).join('; '),
}))

const header = Object.keys(rows[0])
const csv = [header, ...rows.map((r) => header.map((k) => `"${String(r[k]).replace(/"/g, '""')}"`).join(','))]
  .map((line) => line.join('\n'))
  .join('\n')

The two important parts are the flattening (address?.city) and the quoting ("..." with doubled quotes). The quoting is what protects values that contain commas or quotes — data like "Hello, world" must become "Hello, world" in CSV, or the column count breaks.

The errors that actually happen

Most conversion bugs are one of these:

  • Commas inside values. New York, NY contains a comma. Unquoted, it splits into two columns. Rule: quote every field, always.
  • Quotes inside values. A value like He said "hi" needs its quotes doubled (""hi"") or the row corrupts.
  • Missing flatting for nested objects. The converter silently produces columns named [object Object] — a sign the flattening plan wasn’t applied.
  • Type coercion. JSON null becomes an empty cell (fine) but a string "null" stays null (not fine). Know which one you have.
  • Line breaks in values. Multi-line strings break naive converters. A proper converter keeps them inside one quoted cell.

If you end up with broken CSV, the fastest sanity check is the reverse: paste it into a CSV to JSON converter and see whether the structure comes back intact.

The validation checklist

After converting, check:

  • Headers match your intended column plan.
  • Every row has the same number of columns.
  • Commas inside values are quoted, not column-splitting.
  • Nested fields flattened to the columns you chose.
  • null cells are empty and distinct from the string "null".
  • A sample of rows matches the source JSON.

The short version

Convert with a JSON to CSV converter, plan your flattening before you run it, quote every field, and validate the output by converting it back. Get those four right and the conversion is done in minutes instead of a debugging session.