Skip to content
LocalOnly
Converters

How to Convert JSON to CSV in JavaScript and Python

Joining values with commas breaks on the first name that contains one. Here is a short, tested JSON to CSV converter for JavaScript and Python, and the details that make Excel open it correctly.

Updated October 18, 20263 min readTool runs in your browser

To convert JSON to CSV in code, you need correct quoting and a complete header row. The JSON to CSV Converter handles a one-off export in the browser, and its page explains how nested data is squeezed into columns. When the export runs on a schedule or behind a Download button, you need the same conversion in code, and the usual first attempt, joining values with commas, produces a broken file.

This guide gives a tested converter for each language and the details that decide whether the file opens correctly.

Convert JSON to CSV in JavaScript

const csvField = (value) => {
  const text = value === undefined || value === null ? "" : String(value);
  return /[",\n\r]/.test(text) ? '"' + text.replaceAll('"', '""') + '"' : text;
};

function toCsv(rows) {
  const headers = [...new Set(rows.flatMap((row) => Object.keys(row)))];
  const lines = [headers, ...rows.map((row) => headers.map((h) => row[h]))];
  return lines.map((line) => line.map(csvField).join(",")).join("\r\n") + "\r\n";
}

toCsv(records)

Input

[
  { "id": "ord_1", "customer": "O'Brien, Ana", "note": "said \"fragile\"", "total": 120.5 },
  { "id": "ord_2", "customer": "José", "total": 35, "gift": true }
]

Output

id,customer,note,total,gift
ord_1,"O'Brien, Ana","said ""fragile""",120.5,
ord_2,José,,35,true

Three details make this correct. The header is the union of the keys in every record, so gift, which only the second order has, still gets a column. A field containing a comma, a quote or a line break is wrapped in double quotes, with each quote inside doubled, as RFC 4180 describes. And rows end with \r\n, the line ending that standard specifies.

Convert JSON to CSV in Python

import csv

def write_csv(records, path):
    fields = list(dict.fromkeys(key for record in records for key in record))
    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields, restval="")
        writer.writeheader()
        writer.writerows(records)

dict.fromkeys collects every key once in first-seen order, and restval="" fills the cells a record does not have. The csv module does the quoting. Open the file with newline="", as the csv documentation asks; without it, Windows writes an extra line break and every row is followed by a blank line. One small difference from the JavaScript version: Python writes the boolean True where JavaScript writes true.

Nested values

Both converters expect flat records. A nested object such as customer: { name, country } would come out as [object Object] in JavaScript and as a Python dict representation in Python. Flatten each record first, so customer.name and customer.country become their own columns; the JSON Flattener guide has a function for that. For arrays that should stay together, such as a list of tags, write them as one JSON string per cell with JSON.stringify or json.dumps.

Making the file open cleanly in Excel

  • Accents and other non-ASCII text. Excel does not always detect UTF-8 when a CSV file is opened by double-clicking it. Starting the file with a byte order mark, the character \uFEFF, makes it read the file as UTF-8. Write it in Python with encoding="utf-8-sig", or prepend it to the string in JavaScript.
  • Long numbers and leading zeros. Excel shows numbers with at most 15 significant digits and drops leading zeros, so an 18-digit order ID or a postcode such as 007 changes when the file is opened. The data in the file is correct; the display is not. Users who need those columns should import the file and mark the columns as text.
  • Formula injection. A cell that begins with =, +, - or @ can be treated as a formula when the file is opened in a spreadsheet. If any column contains text typed by users, such as names or comments, prefix such values with a single quote or a space before writing them.

Frequently asked questions

Command Palette

Search for a tool or command