How to convert JSON to CSV in Python
Learn how to convert JSON to CSV in Python. This guide covers multiple methods, tips, real-world uses, and common error debugging.

Converting JSON to CSV in Python is a common task for managing and analyzing data. This process transforms structured JSON objects into a tabular format suitable for spreadsheets and data processing pipelines.
In this article, you'll learn several methods for this conversion. We'll provide practical examples, discuss real-world applications, and share debugging tips to help you select the right approach for your specific use case.
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 libraries. The script's efficiency comes from using the csv.DictWriter class, which is specifically designed for cases where your input data is a list of dictionaries—like a parsed JSON array. It directly maps each dictionary's keys to the columns in the output CSV file.
The process is straightforward:
- First, it dynamically grabs the column headers from the keys of the first JSON object using
data[0].keys(). - Next,
writer.writeheader()writes that header row to the CSV file. - Finally,
writer.writerows(data)writes all the dictionary objects as rows in a single, efficient operation.
Basic approaches to JSON conversion
Beyond the straightforward conversion, you'll often encounter trickier data—like nested JSON or records with missing keys—which is where libraries like pandas shine.
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 makes the conversion remarkably concise. After loading the JSON, the code creates a DataFrame—a powerful, two-dimensional data structure—with a single line: pd.DataFrame(data).
- The DataFrame's built-in
to_csv()method handles the entire export process. - You'll want to include
index=Falseto prevent pandas from writing its own row index into the final CSV file.
This approach is not just clean; it's also powerful for handling inconsistencies like missing data, which pandas manages gracefully.
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
Nested JSON requires a flattening step before you can write it to a CSV. This script handles that by merging each nested object with its parent into a single dictionary.
- The core logic is in
{**item, **item.pop('details')}. It uses.pop()to remove the nesteddetailsdictionary, and then the dictionary unpacking operator (**) combines both into a new, flat dictionary.
After this process is repeated for every item, the resulting list of flattened dictionaries is written to the CSV file.
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 don't share the same keys, you need a way to create a complete set of headers. This script first iterates through all your data, collecting every unique key into a single set. This set then becomes the definitive list of fieldnames for the csv.DictWriter.
- The key is the
restval=''parameter, which tells the writer to fill any missing values with an empty string.
This ensures your CSV remains structurally consistent even when the source data isn't, preventing errors and placing empty values where they belong.
Advanced JSON to CSV techniques
For larger or more unpredictable datasets, you'll need advanced techniques for streaming data, customizing fields, and automatically detecting your JSON structure.
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 your JSON files are too large to fit in memory, the ijson library is your best bet. It processes the file as a stream, avoiding the need to load the entire dataset at once. This approach is incredibly memory-efficient, making it ideal for big data tasks.
- The core of this method is
ijson.items(json_file, 'item'), which creates an iterator that yields one JSON object at a time. - The script inspects the first object to dynamically create the CSV headers with
DictWriter. - It then iterates through all objects, writing each one as a row.
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
Sometimes you need more than a direct conversion. This script lets you rename JSON keys to custom CSV headers and transform values on the fly. It all starts with a field_mapping dictionary that defines your desired output columns.
- A dictionary comprehension processes each item, using
field_mapping.get(k, k)to look up and apply new key names. - It also transforms values in the same step. Here, a conditional expression checks if a value is a string and converts it to uppercase with
.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 script automatically discovers the structure of your JSON data, which is useful when you don't know all the possible keys beforehand. It uses a defaultdict(set) to build a schema that tracks every unique key and its associated data types across all records.
- The code iterates through each JSON object, adding the type of each value—like
strorint—to asetfor the corresponding key. - Finally,
list(schema.keys())generates a comprehensive list of all discovered keys to use as headers, ensuring your CSV captures the complete dataset structure.
Move faster with Replit
Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. While the techniques in this article are powerful, you can move from piecing together code to building complete applications with Agent 4.
Instead of just converting data, you can describe the entire tool you want to build, and Agent 4 will take it from idea to working product. You can build tools like:
- A sales reporting utility that pulls nested JSON from an e-commerce API, flattens the order data, and exports it as a clean CSV for analysis.
- A data migration script that processes large, inconsistent JSON user profiles, fills in missing values, and converts them into a structured CSV for a new system.
- A monitoring tool that fetches JSON status updates from multiple endpoints, renames keys for clarity, and appends the transformed data to a single CSV log file.
Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.
Common errors and challenges
While the conversion process is often straightforward, real-world data can throw you a few curveballs. You'll need to be prepared for common issues like malformed JSON, encoding errors, and complex nested structures.
Handling errors with malformed json files
Your script can easily fail if the JSON file isn't perfectly formatted. Even a small mistake, like a trailing comma, will cause the json.load() function to raise a JSONDecodeError. The code below shows what happens when this error is encountered.
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 has no built-in error handling, so a minor syntax flaw in the JSON file will stop it cold. The following code shows how you can add a try-except block to gracefully manage these issues.
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 improved script wraps the conversion logic in a try-except block, making it far more resilient. It catches json.JSONDecodeError if the file has syntax mistakes, like a misplaced comma, and prints a helpful error instead of crashing. It also handles IndexError, which you'll see if the JSON is empty or isn't a list. This prevents the script from failing when it tries to access data[0] for the headers.
Dealing with Unicode encoding issues in CSV output
If your JSON data contains international characters or symbols, you’ll likely encounter a UnicodeEncodeError. This error occurs because Python's default file writing mode doesn't always handle non-ASCII characters. The script below shows what happens when this problem arises.
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)
The script fails because the open() function lacks an encoding parameter, forcing it to use a system default that often can't process international characters. The corrected code below shows how to resolve this.
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)
The solution is to explicitly set the character encoding. By adding encoding='utf-8' to the open() function for both the input and output files, you tell Python how to handle non-ASCII characters correctly. UTF-8 is a universal standard that supports text from nearly any language.
This simple change prevents errors and preserves data integrity. It's an essential step whenever you're working with international text, emojis, or special symbols to ensure they transfer cleanly to your CSV.
Handling nested structures with the json.dumps() function
When your JSON contains a mix of simple values and nested objects, a direct conversion will fail. The csv.DictWriter expects simple values, not dictionaries, for its cells. The script below shows exactly what happens when this mismatch occurs.
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() can't write a nested dictionary into a single cell; it only accepts simple values. The following code shows how to properly format the data before writing to the CSV file.
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 preserves nested structures by converting them into JSON strings. The custom flatten_value function checks if a value is a list or dictionary and, if so, uses json.dumps() to serialize it. This turns complex objects into a single string that can be written into a CSV cell. It's a useful approach when you need to keep the nested data intact within the CSV, rather than flattening it into separate columns.
Real-world applications
Moving beyond troubleshooting, these conversion skills are essential for practical workflows like analyzing API data and batch-processing entire directories of JSON files.
Converting API response data with requests to CSV
A common workflow involves using the requests library to fetch JSON data from an API and then writing it directly to a CSV file for analysis.
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 demonstrates how to pull data from a live API and save a specific subset of it to a CSV. It uses the requests library to fetch user data, and response.json() automatically parses the JSON into a list of dictionaries.
- The key is that it manually defines the desired columns in the
fieldnameslist, giving you full control over the output. - A dictionary comprehension—
{field: user[field] for field in fieldnames}—filters each user object, keeping only the specified fields before writing the row.
Batch processing multiple JSON files with os.listdir()
When you're dealing with a whole directory of JSON files, you can use os.listdir() to automatically read and combine them all into one master CSV.
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 the consolidation of data from an entire directory of JSON files. It iterates through each file in the data_files folder, loading its contents and appending them to a master list.
- It dynamically builds a complete set of headers by collecting every unique key from all files using
all_fields.update(). - For traceability, it adds a
source_filecolumn to each row, noting the original filename.
The script then writes all the aggregated data into a single, comprehensive CSV file, ensuring no data is lost even if the JSON files have different structures.
Get started with Replit
Turn what you've learned into a working application with Replit Agent. Just describe your tool, like: "Build a utility that pulls GitHub user data and saves it as a CSV" or "Create a script to combine JSON log files into one CSV."
Replit Agent writes the code, tests for errors, and deploys the app. Start building with Replit.
Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.
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.

.png)
.png)
.png)