How to convert JSON to CSV in Python

Your guide to converting JSON to CSV in Python. Explore various methods, tips, real-world applications, and how to debug common errors.

How to convert JSON to CSV in Python
Published on: 
Tue
Mar 3, 2026
Updated on: 
Wed
Mar 4, 2026
The Replit Team Logo Image
The Replit Team

You can easily convert JSON to CSV in Python for data transformation. This task structures complex, nested data into a tabular format for easier analysis and spreadsheet compatibility.

Here, you'll explore various conversion techniques and practical tips. You'll also find real-world applications and debugging advice to help you navigate common challenges and streamline your data processing workflow.

Basic json to csv conversion

import json
import csv

with open('data.json', 'r') as json_file:
   data = json.load(json_file)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
   writer.writeheader()
   writer.writerows(data)--OUTPUT--name,age,city
John,30,New York
Alice,25,Los Angeles
Bob,35,Chicago

This approach uses Python’s built-in json and csv modules for a direct conversion. The key is using the csv.DictWriter class, which is perfect when your JSON file contains an array of objects. It maps Python dictionaries directly to CSV rows, making the code clean and efficient.

The script works in a few simple steps:

  • It dynamically creates CSV headers by extracting keys from the first dictionary in your data using data[0].keys().
  • The writer.writeheader() method writes these keys as the first row in the CSV file.
  • Finally, writer.writerows(data) iterates through the entire list of dictionaries and writes each one as a separate row.

Basic approaches to JSON conversion

Moving beyond the basics, you can tackle complex data—like nested structures or records with missing keys—by converting it into a pandas.DataFrame.

Using pandas.DataFrame for conversion

import pandas as pd
import json

with open('data.json', 'r') as file:
   data = json.load(file)
   
df = pd.DataFrame(data)
df.to_csv('output.csv', index=False)--OUTPUT--name,age,city
John,30,New York
Alice,25,Los Angeles
Bob,35,Chicago

Using the pandas library offers a more powerful way to handle JSON to CSV conversion, especially for complex datasets. It streamlines the process into just a few lines of code.

  • The script first loads your JSON data, then passes it directly to pd.DataFrame() to create a structured, two-dimensional table.
  • Pandas is smart enough to handle records with missing keys by automatically inserting empty values, ensuring your table remains consistent.
  • Finally, the to_csv() method writes the DataFrame to a file. Setting index=False is important—it prevents pandas from adding an extra, unwanted index column to your output CSV.

Converting nested JSON structures

import json
import csv

with open('nested_data.json', 'r') as file:
   data = json.load(file)

flattened_data = []
for item in data:
   flat_item = {**item, **item.pop('details')}
   flattened_data.append(flat_item)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=flattened_data[0].keys())
   writer.writeheader()
   writer.writerows(flattened_data)--OUTPUT--name,email,phone,address
John,[email protected],555-1234,123 Main St
Alice,[email protected],555-5678,456 Oak Ave

When your JSON contains nested objects, you need to flatten the structure before converting it to CSV. This script prepares the data by merging the nested key-value pairs into the top-level dictionary.

  • The core of this process is the line flat_item = {**item, **item.pop('details')}.
  • The item.pop('details') method extracts the nested dictionary while removing it from the parent object.
  • The dictionary unpacking operator ** then merges the keys from both the parent and the extracted nested dictionary into a new, single-level dictionary.

The result is a list of flat dictionaries, which is perfect for writing to a CSV file using DictWriter.

Handling missing keys in JSON

import json
import csv

with open('inconsistent_data.json', 'r') as file:
   data = json.load(file)

all_keys = set()
for item in data:
   all_keys.update(item.keys())
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=all_keys, restval='')
   writer.writeheader()
   writer.writerows(data)--OUTPUT--name,age,city,email
John,30,New York,[email protected]
Alice,25,Los Angeles,
Bob,35,,[email protected]
Charlie,,,[email protected]

When your JSON objects have inconsistent keys, this approach ensures a clean conversion. The script first iterates through the entire dataset to build a set of all unique keys. This creates a complete and accurate header for your CSV file, covering every possible field.

  • The key is the restval='' parameter in csv.DictWriter.
  • It automatically fills in any missing values with an empty string.
  • This prevents errors and guarantees your final CSV has a consistent structure, with each row containing the same number of columns.

Advanced JSON to CSV techniques

Building on those foundational methods, you can now handle more complex challenges like processing massive files, customizing field mappings, and automating schema detection.

Processing large JSON files with ijson

import csv
import ijson

csv_file = open('large_output.csv', 'w', newline='')
writer = None

with open('large_data.json', 'rb') as json_file:
   objects = ijson.items(json_file, 'item')
   for i, obj in enumerate(objects):
       if i == 0:
           writer = csv.DictWriter(csv_file, fieldnames=obj.keys())
           writer.writeheader()
       writer.writerow(obj)
       
csv_file.close()--OUTPUT--name,age,city
John,30,New York
Alice,25,Los Angeles
...

When you're working with massive JSON files, loading everything into memory can cause your program to crash. The ijson library solves this by streaming the data. This approach is incredibly memory-efficient because it reads and processes the file piece by piece instead of all at once.

  • The script uses ijson.items() to create an iterator that yields each object from the JSON array one by one.
  • It inspects the very first object to dynamically determine the CSV headers.
  • Each object is then immediately written as a row to the CSV file, keeping memory usage minimal throughout the process.

Custom field mapping and transformation

import json
import csv

field_mapping = {'user_name': 'Name', 'user_age': 'Age', 'location': 'City'}

with open('data.json', 'r') as json_file:
   data = json.load(json_file)
   
transformed_data = []
for item in data:
   transformed = {field_mapping.get(k, k): v.upper() if isinstance(v, str) else v
                 for k, v in item.items()}
   transformed_data.append(transformed)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=field_mapping.values())
   writer.writeheader()
   writer.writerows(transformed_data)--OUTPUT--Name,Age,City
JOHN,30,NEW YORK
ALICE,25,LOS ANGELES

This technique gives you precise control over the output by renaming fields and transforming data on the fly. You define how to map old keys to new column names in a field_mapping dictionary, which makes your final CSV more readable.

  • A dictionary comprehension iterates through each JSON object, applying your custom rules.
  • The field_mapping.get(k, k) method renames keys, falling back to the original key if no mapping is specified.
  • You can also modify values directly—in this case, converting all strings to uppercase using .upper().

Automated schema detection for JSON conversion

import json
import csv
from collections import defaultdict

with open('complex_data.json', 'r') as file:
   data = json.load(file)

# Auto-detect schema
schema = defaultdict(set)
for item in data:
   for key, value in item.items():
       schema[key].add(type(value).__name__)

with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=list(schema.keys()))
   writer.writeheader()
   writer.writerows(data)--OUTPUT--name,age,active,score
John,30,True,85.5
Alice,25,False,92.3
Bob,35,True,78.9

This approach automatically discovers the complete schema from JSON data where objects have inconsistent keys. It ensures every possible field becomes a column in your final CSV file, creating a clean, unified table from a messy source.

  • The script uses a defaultdict to efficiently collect all unique keys from every object in your dataset without raising errors.
  • It then creates the CSV headers dynamically using the collected keys from schema.keys().
  • This guarantees a consistent structure, as DictWriter automatically handles any missing values in a given row.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. It's designed to help you build and deploy software directly from a description of what you want to create.

You can use Replit Agent to turn the concepts from this article into production applications. It builds complete apps—with databases, APIs, and deployment—directly from your instructions. For the JSON to CSV methods we've covered, Replit Agent can build practical tools:

  • Build a data normalization tool that flattens nested JSON from API responses and converts it into a clean CSV file.
  • Create a log processor that streams large JSON log files using an iterator like ijson and converts them to CSV without running out of memory.
  • Deploy a data migration utility that applies custom field mappings to transform and rename data while converting it from JSON to CSV.

Describe your app idea, and Replit Agent will write the code, test it, and fix issues automatically. You can go from concept to a deployed application entirely within your browser.

Common errors and challenges

Even with the right tools, you might hit a few snags, but most common errors are straightforward to fix.

Handling errors with malformed json files

A malformed JSON file is a frequent culprit, often due to a simple syntax error like a trailing comma or a missing bracket. When this happens, Python’s json module will raise a JSONDecodeError, stopping your script. You can prevent crashes by wrapping your file-loading logic in a try...except block to catch the error and handle it gracefully.

Dealing with Unicode encoding issues in CSV output

Unicode characters—like emojis or accented letters—can cause encoding headaches. JSON typically uses UTF-8, but CSVs can be tricky. If you don't specify an encoding, special characters might appear garbled in your output file. The solution is to explicitly set the encoding to utf-8 when opening your CSV file for writing, ensuring all characters are preserved correctly.

Handling nested structures with the json.dumps() function

While flattening nested JSON is a common approach, sometimes you might want to keep the nested structure intact within a single CSV cell. You can achieve this by using the json.dumps() function to convert a nested dictionary or list into a JSON-formatted string. This technique is useful when you need to store complex data in one column for later processing, rather than spreading it across many columns.

Handling errors with malformed json files

A simple syntax mistake in your JSON file, like a misplaced comma, can bring your entire conversion script to a halt. The json.load() function is strict and will raise an error immediately, preventing any data from being processed. See it in action below.

import json
import csv

with open('data.json', 'r') as json_file:
   data = json.load(json_file)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
   writer.writeheader()
   writer.writerows(data)

The script attempts to parse the file directly with json.load(). Without any error handling, a single syntax flaw in the JSON causes the entire program to fail. The next snippet shows how to handle this gracefully.

import json
import csv

try:
   with open('data.json', 'r') as json_file:
       data = json.load(json_file)
       
   with open('output.csv', 'w', newline='') as csv_file:
       writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
       writer.writeheader()
       writer.writerows(data)
except json.JSONDecodeError as e:
   print(f"JSON parsing error: {e}")
except IndexError:
   print("Error: JSON data is empty or not a list of objects")

This solution makes your script more resilient by wrapping the conversion logic in a try...except block. This approach anticipates common data issues and prevents your program from crashing unexpectedly.

  • It catches a json.JSONDecodeError if the file has syntax mistakes.
  • It also handles an IndexError, which occurs if the JSON is empty or not structured as a list of objects, preventing data[0].keys() from failing.

Dealing with Unicode encoding issues in CSV output

When your JSON data contains international characters or emojis, you'll often run into encoding problems. The default settings don't always preserve these characters, resulting in garbled output. The following code demonstrates what happens when encoding isn't specified during the conversion.

import json
import csv

with open('international_data.json', 'r') as json_file:
   data = json.load(json_file)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
   writer.writeheader()
   writer.writerows(data)

By not defining an encoding when calling open(), the script defaults to your system's setting. If that setting isn't UTF-8, it can't process special characters from the JSON, causing errors. See how to correct this below.

import json
import csv

with open('international_data.json', 'r', encoding='utf-8') as json_file:
   data = json.load(json_file)
   
with open('output.csv', 'w', newline='', encoding='utf-8') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
   writer.writeheader()
   writer.writerows(data)

This solution prevents garbled text by explicitly setting the character encoding. The key is adding encoding='utf-8' when opening both the JSON source and the CSV destination file. This simple fix guarantees data integrity by ensuring special characters like emojis or accented letters are preserved correctly during conversion. It's a crucial step whenever you're working with international or non-standard text data, making sure what you read is exactly what gets written.

Handling nested structures with the json.dumps() function

Flattening isn't always the goal. Sometimes you need to keep nested data intact as a string in a single CSV cell. Directly writing a dictionary or list will cause an error, as CSVs can't handle complex objects. See what happens below.

import json
import csv

with open('mixed_data.json', 'r') as json_file:
   data = json.load(json_file)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
   writer.writeheader()
   writer.writerows(data)

The script fails because writer.writerows() attempts to write a dictionary into a single cell. CSVs can only contain simple values, not complex objects. The following code shows how to correctly format this nested data for writing.

import json
import csv

def flatten_value(value):
   if isinstance(value, (list, dict)):
       return json.dumps(value)
   return value

with open('mixed_data.json', 'r') as json_file:
   data = json.load(json_file)

processed_data = []
for item in data:
   processed_item = {k: flatten_value(v) for k, v in item.items()}
   processed_data.append(processed_item)
   
with open('output.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
   writer.writeheader()
   writer.writerows(processed_data)

This solution keeps nested data intact by converting complex objects into JSON-formatted strings. The script processes each row before writing:

  • A helper function, flatten_value, checks each value.
  • If a value is a list or dictionary, it's serialized into a string using json.dumps().

This allows you to store the entire nested structure within a single CSV cell. It's perfect when you need to preserve the original data structure for later processing instead of flattening it across multiple columns.

Real-world applications

With these conversion techniques, you can tackle common data workflows like processing API responses or batch-converting multiple JSON files.

Converting API response data with requests to CSV

A common workflow is to use the requests library to fetch data from an API and write the JSON response directly to a CSV file.

import requests
import json
import csv

# Fetch data from a public API
response = requests.get('https://jsonplaceholder.typicode.com/users')
users = response.json()

# Write to CSV
with open('users.csv', 'w', newline='') as csv_file:
   fieldnames = ['id', 'name', 'email', 'phone']
   writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
   writer.writeheader()
   for user in users:
       writer.writerow({field: user[field] for field in fieldnames})

This script shows how to pull data from a public API and write a curated selection to a CSV file. It uses requests.get() to fetch the data, which is then parsed into a Python list with response.json().

  • A predefined fieldnames list specifies exactly which columns you want in your final CSV.
  • The script iterates through each user, building a new dictionary that contains only the desired fields.
  • Finally, csv.DictWriter writes these filtered records row by row, creating a clean and specific output.

Batch processing multiple JSON files with os.listdir()

For batch processing, you can use the os.listdir() function to read all JSON files from a folder and consolidate them into a single, unified CSV file.

import json
import csv
import os

json_dir = 'data_files'
all_data = []
all_fields = set()

for filename in os.listdir(json_dir):
   if filename.endswith('.json'):
       file_path = os.path.join(json_dir, filename)
       with open(file_path, 'r') as json_file:
           data = json.load(json_file)
           for item in data:
               item['source_file'] = filename
               all_fields.update(item.keys())
               all_data.append(item)

with open('combined_data.csv', 'w', newline='') as csv_file:
   writer = csv.DictWriter(csv_file, fieldnames=all_fields)
   writer.writeheader()
   writer.writerows(all_data)

This script automates combining multiple JSON files into one CSV. It uses os.listdir() to find every file ending in .json within a directory. As it processes each file, it performs two key actions:

  • It adds a source_file key to each record, letting you trace data back to its origin.
  • It collects every unique field name into a set, which dynamically creates a complete header for the final CSV.

Finally, it writes all the aggregated data into a single file, ensuring a consistent structure across all records.

Get started with Replit

Put these techniques into practice by building a real tool with Replit Agent. Describe what you want, like “a web app that converts uploaded JSON files to CSV” or “a script that pulls API data and saves it as a CSV.”

Replit Agent writes the code, tests for errors, and deploys your application for you. Start building with Replit and bring your idea to life.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.