Unit 5 • Lesson 4

Reading JSON Data

Overview

A list of records is a table waiting to happen.

Intermediate 20–25 min

What You Will Learn in This Lesson

By the end of this lesson, you will be able to:

  • Turn a list of dictionaries into a DataFrame.
  • Say what happens to a record that is missing a key.
  • Explain why the column order is not guaranteed to be the key order.
  • Flatten one level of nesting.

Why This Matters

JSON is what an API gives you, and it is record-shaped rather than column-shaped. pandas bridges the two in one call — but the bridge makes decisions about missing keys and about nesting, and knowing them saves you from a column of dictionaries.

Step 1: Records in, table out

JSON from an API is usually a list of objects, and each object is a row. DataFrame takes that shape directly.

1

A list of dictionaries

The union of all the keys becomes the columns. Each record becomes a row.

import pandas as pd

records = [
    {"name": "Ada", "score": 92},
    {"name": "Grace", "score": 88},
]
print(pd.DataFrame(records))
2

From a JSON string

When the JSON arrives as text, parse it first and build from the result. read_json exists too, but going through json.loads keeps the parsing and the table-building as two steps you can inspect separately.

import json
import pandas as pd

text = '[{"name": "Ada", "score": 92}]'
print(pd.DataFrame(json.loads(text)))

Mini Practice #1: Records to table

Try It Yourself

Build a table from these records and print its shape and columns.

Press Run to see output

Step 2: Missing keys become missing values

A record without a key does not break the table. That column simply has a gap on that row.

1

The gap

The column exists because some record had it. The rows that did not get NaN, and the column widens to float if it was holding whole numbers.

import pandas as pd

records = [{"name": "Ada", "score": 92}, {"name": "Grace"}]
df = pd.DataFrame(records)
print(df)
print(df.dtypes)
2

Nesting does not flatten itself

A value that is itself a dictionary becomes a column of dictionaries, which is almost never what you want. json_normalize flattens it into real columns.

import pandas as pd

records = [{"name": "Ada", "at": {"city": "Leeds", "year": 1843}}]
print(pd.DataFrame(records))
print()
print(pd.json_normalize(records))

The flattened names are joined with a dot: at.city. Rename them if a dot in a column name is going to be awkward later.

Mini Practice #2: Flatten the nesting

Try It Yourself

Build this twice — with DataFrame and with json_normalize — and compare the columns.

Press Run to see output

Step 3: When to Use It

A list of records

JSON from an API is often a list of objects, which becomes a table with one call.

pd.DataFrame(records)

Nested objects

json_normalize flattens nested fields into columns with dotted names.

When Not to Use It

Do not load deeply nested JSON straight into a DataFrame and expect columns. Cells full of dictionaries need flattening first.

End-of-Lesson Exercises

Exercise 1: Columns from records

Write from_records(rows) that turns a list of dictionaries into a table and returns its column names, sorted.

pd.DataFrame takes the list of dictionaries directly. sorted(df.columns) then gives plain strings in a predictable order.

Press Run to try it, then Check my work to mark it.

Exercise 2: How complete is each record

Write completeness(rows) that builds a table from the records and returns a dictionary mapping each column name to how many rows actually have a value for it.

df.notna().sum() gives a Series of counts per column. Turn it into a dict and make the values plain ints with a comprehension.

Press Run to try it, then Check my work to mark it.