X Xerobit

JSON to CSV Converter — Convert JSON Arrays to CSV Format

Converting JSON to CSV flattens JSON arrays into rows for spreadsheet import. Here's how to convert JSON arrays to CSV in JavaScript and Python, handle nested objects, and deal...

Mian Ali Khalid · · 5 min read
Use the tool
CSV to JSON Converter
Convert CSV files to JSON with proper quoting and escaping.
Open CSV to JSON Converter →

Converting JSON to CSV transforms JSON arrays into tabular format for spreadsheets, data analysis tools, and database imports. The conversion is straightforward for flat JSON objects but requires decisions for nested objects and arrays.

Use the CSV to JSON Converter to convert between CSV and JSON formats.

Basic JSON to CSV conversion

Given flat JSON array:

[
  { "id": 1, "name": "Alice", "email": "alice@example.com", "age": 30 },
  { "id": 2, "name": "Bob", "email": "bob@example.com", "age": 25 },
  { "id": 3, "name": "Charlie", "email": "charlie@example.com", "age": 35 }
]

Output CSV:

id,name,email,age
1,Alice,alice@example.com,30
2,Bob,bob@example.com,25
3,Charlie,charlie@example.com,35

JavaScript conversion

Manual implementation

function jsonToCsv(data) {
  if (!data || data.length === 0) return '';
  
  // Get all unique column names from all objects:
  const columns = [...new Set(data.flatMap(Object.keys))];
  
  // Header row:
  const header = columns.map(escapeField).join(',');
  
  // Data rows:
  const rows = data.map(row => 
    columns.map(col => {
      const value = row[col] ?? '';  // Use empty string for missing fields
      return escapeField(String(value));
    }).join(',')
  );
  
  return [header, ...rows].join('\n');
}

function escapeField(value) {
  // Quote if contains comma, newline, or double quote:
  if (/[,\n"]/.test(value)) {
    return '"' + value.replace(/"/g, '""') + '"';
  }
  return value;
}

// Usage:
const json = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob, Jr.', email: 'bob@example.com' },
];

const csv = jsonToCsv(json);
console.log(csv);
/*
id,name,email
1,Alice,alice@example.com
2,"Bob, Jr.",bob@example.com
*/

Using Papa Parse (download)

import Papa from 'papaparse';

const data = [
  { id: 1, name: 'Alice', email: 'alice@example.com', age: 30 },
  { id: 2, name: 'Bob', email: 'bob@example.com', age: 25 },
];

const csv = Papa.unparse(data, {
  header: true,        // Include header row
  delimiter: ',',      // Comma delimiter
  newline: '\n',       // Line ending
  quoteChar: '"',      // Quote character
  skipEmptyLines: true,
});

console.log(csv);

// Download as file in browser:
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', 'data.csv');
link.click();

Python conversion

Using csv module

import csv
import json
import io

data = [
    {"id": 1, "name": "Alice", "email": "alice@example.com"},
    {"id": 2, "name": "Bob", "email": "bob@example.com"},
]

# Write to file:
with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    if data:
        writer = csv.DictWriter(f, fieldnames=data[0].keys())
        writer.writeheader()
        writer.writerows(data)

# Write to string:
output = io.StringIO()
writer = csv.DictWriter(output, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
csv_string = output.getvalue()

Using pandas

import pandas as pd
import json

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

df = pd.DataFrame(data)
df.to_csv('output.csv', index=False, encoding='utf-8')

Handling nested JSON objects

Nested objects must be flattened:

[
  {
    "id": 1,
    "name": "Alice",
    "address": { "city": "New York", "state": "NY" },
    "scores": [95, 87, 92]
  }
]

Option 1: Flatten nested objects

function flattenObject(obj, prefix = '') {
  return Object.keys(obj).reduce((acc, key) => {
    const fullKey = prefix ? `${prefix}.${key}` : key;
    if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
      Object.assign(acc, flattenObject(obj[key], fullKey));
    } else {
      acc[fullKey] = Array.isArray(obj[key]) ? JSON.stringify(obj[key]) : obj[key];
    }
    return acc;
  }, {});
}

const flattened = flattenObject({
  id: 1,
  name: 'Alice',
  address: { city: 'New York', state: 'NY' },
  scores: [95, 87, 92],
});

/*
{
  id: 1,
  name: 'Alice',
  'address.city': 'New York',
  'address.state': 'NY',
  scores: '[95,87,92]'
}
*/

Option 2: Stringify nested values

function jsonToCsvWithNested(data) {
  const columns = [...new Set(data.flatMap(Object.keys))];
  const rows = data.map(row =>
    columns.map(col => {
      const value = row[col] ?? '';
      if (typeof value === 'object') {
        return `"${JSON.stringify(value).replace(/"/g, '""')}"`;
      }
      return escapeField(String(value));
    }).join(',')
  );
  return [columns.join(','), ...rows].join('\n');
}

Option 3: Normalize before converting

For data with arrays like order items, expand to multiple rows:

// One row per order item:
const rows = orders.flatMap(order =>
  order.items.map(item => ({
    order_id: order.id,
    customer: order.customer,
    item_name: item.name,
    item_price: item.price,
    item_qty: item.qty,
  }))
);

Handling missing fields

JSON objects may have different keys. Handle missing fields with defaults:

const data = [
  { id: 1, name: 'Alice', email: 'alice@example.com', phone: '555-1234' },
  { id: 2, name: 'Bob', email: 'bob@example.com' },  // Missing phone
  { id: 3, name: 'Charlie', phone: '555-5678' },      // Missing email
];

// Get all unique columns:
const columns = [...new Set(data.flatMap(Object.keys))];
// ["id", "name", "email", "phone"]

// Missing fields default to empty string:
const rows = data.map(row =>
  columns.map(col => row[col] ?? '').join(',')
);

/*
id,name,email,phone
1,Alice,alice@example.com,555-1234
2,Bob,bob@example.com,
3,Charlie,,555-5678
*/

Excel compatibility

Excel uses semicolons in some locales and requires a BOM for UTF-8:

// Add UTF-8 BOM for Excel compatibility:
const BOM = '';
const csvWithBom = BOM + csv;

// For European locales (semicolon delimiter):
Papa.unparse(data, { delimiter: ';' });

Related posts

Related tool

CSV to JSON Converter

Convert CSV files to JSON with proper quoting and escaping.

Written by Mian Ali Khalid. Part of the Data & Format pillar.