Listen up. If you're going to process data in Python, you need to understand Reading JSON Files in Python. This is where data engineers separate themselves from script kiddies. It's about writing code that scales.
1Pandas read json Part 1
REST APIs overwhelmingly speak JSON, so pd.read_json() is often the first function standing between a live API response and a usable DataFrame. Called with just a path or URL, pd.read_json('data.json') parses the file and tries to infer how it maps to rows and columns automatically ā but that inference only works reliably for a handful of common shapes.
That's where the orient argument comes in: it tells Pandas explicitly how the JSON is structured. orient='records' is the shape most APIs actually return ā a list of flat objects like [{"id": 1, "name": "Pop"}, {"id": 2, "name": "Lolly"}] ā while other orientations ('columns', 'index', 'split') describe JSON that's already organized column-by-column or keyed by row index. Picking the wrong orient doesn't always raise an error; it can just as easily produce a DataFrame with the wrong shape or columns full of dictionaries.
Real API payloads are rarely flat, though ā a user record might nest an address object inside it, or a list of tags inside that. read_json() alone leaves those nested structures as Python dicts/lists sitting inside single cells, which is unusable for filtering or aggregation. pd.json_normalize() solves that by flattening nested dictionaries into their own dot-separated columns (e.g. address.city, address.zip), turning deeply nested JSON into a proper tabular DataFrame. And the round trip back out uses .to_json(), which serializes a DataFrame back into a JSON string or file for sending to another API or service.
# Example
import pandas as pd
print("Running Pandas...")Data processed and aggregated.
2Step-by-Step Breakdown
JSON (JavaScript Object Notation) is the language of the web. Most REST APIs return data as JSON. Pandas can read it natively.
Which function is used to load a JSON file into a Pandas DataFrame?
- āpd.load_json()
- āpd.read_json()
- āpd.parse_web()
JSON data can be structured in many different ways. In Pandas, we use the "orient" argument to specify how the JSON maps to rows and columns.
If your JSON file contains a list of dictionaries (like [{"id": 1, "name": "Pop"}]), which orient argument should you use?
- āorient='columns'
- āorient='records'
- āorient='index'
Sometimes JSON data is deeply nested (dictionaries inside dictionaries). Standard read_json fails here. We use json_normalize to flatten it.
If an API returns deeply nested JSON, which Pandas function should you use to flatten the nested dictionaries into columns?
- āpd.flatten_json()
- āpd.read_json(nested=True)
- āpd.json_normalize()
Now, prepare yourself. We are about to enter the ADA Defense Protocol. Ensure you understand how to export back to JSON.
ADA DEFENSE: You want to send your DataFrame data back to a web API. Which method exports a DataFrame to a JSON string or file?
- ā.to_json()
- ā.export_json()
- ā.write_web()
Threat neutralized. Web compatibility achieved. You can now communicate with APIs.
Threat neutralized. Concept validated. Proceed to the next section.
Parse Real JSON Records. Finish load_records(): use orient="records" for a JSON list of row-objects.
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1Document the Expected orient Up Front
Because the wrong orient can silently produce a misshapen DataFrame instead of an error, leaving a comment noting the JSON's actual structure next to the read_json() call saves the next reader from re-diagnosing the shape from scratch.
# API returns: [{"id": 1, "name": "Pop"}, ...]
df = pd.read_json(response_text, orient='records')SEO Implications
- 1
'read_json orient' and 'flatten nested json pandas' Search Intent
Handling nested JSON API responses is one of the most common real-world Pandas pain points, so precise coverage of orient and json_normalize targets high-intent developer searches.
Best Practices
Inspect Raw JSON Structure Before Calling read_json()
Print or eyeball a sample of the raw JSON first ā knowing whether it's a list of records, a dict of columns, or deeply nested determines which orient (or whether json_normalize) you actually need.
Use json_normalize() for Nested API Responses
Don't leave nested dictionaries sitting inside single DataFrame cells ā flatten them with json_normalize() immediately after loading so downstream filtering and aggregation work on real columns.
Frequent Bugs
Calling pd.read_json() on deeply nested JSON without json_normalize(), leaving whole cells filled with unusable nested Python dicts instead of separate columns.
Load the raw JSON with the json module first, then pass it through pd.json_normalize() to flatten nested keys into their own columns.
Real-World Examples
Flattening a Nested User API Response
An API returns user records where the address is a nested object: [{"id": 1, "name": "Pop", "address": {"city": "NYC", "zip": "10001"}}] ā the nested address needs to become its own columns.
import json
with open('users.json') as f:
data = json.load(f)
df = pd.json_normalize(data)
print(df.columns)
# Index(['id', 'name', 'address.city', 'address.zip'], dtype='object')