SECTION 1
Historical Context & Motivation
In the early days of the internet, programs needed a standard way to exchange information. Imagine two apps trying to talk to each other — one written in Python, the other in JavaScript. Without a shared language for data, they would be like two people speaking completely different languages with no translator. JSON (JavaScript Object Notation) was created to solve exactly this problem. It provides a simple, human-readable text format that virtually every programming language can understand.
1999 • XML Dominates Data Exchange
2001 • Douglas Crockford Proposes JSON
2006 • JSON Becomes an Internet Standard (RFC 4627)
2008 • Python 2.6 Ships with Built-in json Module
json module to its standard library, so developers no longer needed third-party packages. This made reading and writing JSON a one-import operation.2020s • JSON Everywhere
So the core question this lesson addresses is: how do you take Python data structures — dictionaries, lists, strings, and numbers — and convert them into JSON text that can be saved to a file or sent across the internet, and then convert that text back into Python objects? That is exactly what Python's json module does.
SECTION 2
Core Principles & Definitions
Before diving into code, you need to understand a few foundational ideas. JSON is a text-based data format — it is always a string of characters, never raw binary data. Python's json module bridges the gap between Python objects (like dictionaries and lists) and that text representation. The two main operations are serialization (converting Python objects to JSON text) and deserialization (converting JSON text back into Python objects).
Serialization (Encoding)
json.dumps() for strings or json.dump() for files.Deserialization (Decoding)
json.loads() for strings or json.load() for files. The 's' stands for 'string.'JSON Data Types
The Four Key Functions
s work with strings (dumps, loads). Functions without s work with files (dump, load).KEY TAKEAWAY
json.dumps() is the packing machine, and json.loads() is the unboxing tool.SECTION 3
Visual Explanation — The Serialization Pipeline
json module. The top half illustrates in-memory string conversion: json.dumps() (cyan arrow) encodes Python objects to JSON strings, and json.loads() (pink arrow) decodes them back. The bottom half shows file I/O: json.dump() writes directly to a file, while json.load() reads from one.Notice the naming pattern in the diagram. The letter s at the end of dumps and loads stands for string. These two functions work entirely in memory — they produce or consume a Python string. The versions without s (dump and load) operate on file objects, reading from or writing to actual files on disk. This is the single most important naming distinction to memorize when working with the json module.
SECTION 4
How It Works — Type Mapping Between Python and JSON
When the json module serializes a Python object, it must translate each Python type into a corresponding JSON type. This mapping is deterministic — the same Python value always produces the same JSON output. Understanding this mapping is crucial because JSON supports fewer types than Python, so some information can be lost in translation.
| Python Type | JSON Representation | Example |
|---|---|---|
dict | object | {"key": "value"} |
list / tuple | array | [1, 2, 3] |
str | string | "hello" |
int / float | number | 42 or 3.14 |
True / False | true / false | Note the lowercase in JSON |
None | null | Python's None becomes null |
Python-to-JSON type mapping — the json module handles these conversions automatically.
Watch Out: Tuples Become Lists
tuple like (1, 2, 3), it becomes a JSON array [1, 2, 3]. When you deserialize it back, you get a Python list, not a tuple. This is one of the subtle 'lossy' conversions to be aware of. Similarly, Python set objects cannot be serialized to JSON at all — you must convert them to a list first.The conversion also works in reverse. When json.loads() encounters a JSON object, it creates a Python dict. A JSON array becomes a Python list. JSON true becomes Python True, and JSON null becomes Python None. The process is straightforward and predictable.
SECTION 5
The Four Core Functions in Detail
Now that you understand the type mapping, let's look at each function's syntax and optional parameters. Each function has useful keyword arguments that control formatting and behavior.
indent parameter is especially useful during development because it formats the output with line breaks and spaces, making it easy to read.The indent parameter deserves special attention. By default, json.dumps() outputs everything on a single line with no extra whitespace. While this is efficient for sending data over a network, it is hard for humans to read. Setting indent=2 or indent=4 adds line breaks and indentation, producing neatly formatted output that is much easier to inspect during development.
Pro Tip: sort_keys for Consistency
sort_keys=True, the JSON output will have its keys in alphabetical order every time. This is handy when you want to compare two JSON files side by side, because the keys will always appear in the same order regardless of how the dictionary was built in Python.SECTION 6
Worked Example — Saving and Loading a Student Record
Let's walk through a complete, real-world example. Suppose you are building a program that tracks student information. You want to save a student's data to a JSON file, then read it back later.
Save and Load a Student Record with the json Module
- 1
Step 1 — Import the Module
Start by importing thejsonmodule. It is part of Python's standard library, so no installation is needed.import json - 2
Step 2 — Create a Python Dictionary
Define a dictionary that holds the student's information. This dictionary contains strings, an integer, a list, and a float — all types that JSON supports.student = {"name": "Maya", "age": 16, "gpa": 3.85, "courses": ["AP CS", "Calculus", "English"], "graduated": False} - 3
Step 3 — Write to a JSON File (json.dump)
Open a file in write mode ("w") and usejson.dump()to serialize the dictionary directly into the file. We useindent=2to make the file human-readable.with open("student.json", "w") as f: json.dump(student, f, indent=2) - 4
Step 4 — Inspect the File Contents
If you openstudent.jsonin a text editor, you will see neatly formatted JSON. Notice that Python'sFalsehas becomefalse(lowercase), following JSON conventions.{ "name": "Maya", "age": 16, "gpa": 3.85, "courses": ["AP CS", "Calculus", "English"], "graduated": false } - 5
Step 5 — Read from the JSON File (json.load)
To read the data back, open the file in read mode ("r") and usejson.load(). The result is a regular Python dictionary that you can use like any other.with open("student.json", "r") as f: loaded = json.load(f) print(loaded["name"]) # Maya print(loaded["courses"]) # ['AP CS', 'Calculus', 'English'] - 6
Step 6 — Convert to/from Strings (json.dumps / json.loads)
Sometimes you need a JSON string rather than a file — for example, to send data over a network. Usejson.dumps()to create the string andjson.loads()to parse it back.json_string = json.dumps(student, indent=2) print(type(json_string)) # <class 'str'> parsed = json.loads(json_string) print(type(parsed)) # <class 'dict'>
KEY TAKEAWAY
with open(...) context manager is essential when working with files. It automatically closes the file when the block ends, even if an error occurs. Always pair json.dump() and json.load() with a with statement to keep your code clean and safe.SECTION 7
JSON vs. Other Data Formats
JSON is not the only way to store structured data. Two common alternatives are CSV (Comma-Separated Values) and XML (Extensible Markup Language). Each format has strengths and trade-offs depending on your use case.
| Feature | JSON | CSV | XML |
|---|---|---|---|
| Human Readable? | Yes — clean and compact | Yes — looks like a spreadsheet | Somewhat — verbose tags |
| Nested Data? | Yes — objects inside objects | No — flat rows only | Yes — nested tags |
| Data Types? | Strings, numbers, bools, null, arrays, objects | Everything is a string | Everything is a string (needs schema) |
| File Size | Small to medium | Very small (minimal overhead) | Large (closing tags add bulk) |
| Best For | APIs, config files, structured data | Tabular data (spreadsheets) | Document markup, legacy systems |
Comparison of common data interchange formats
WHEN TO USE JSON
SECTION 8
Connection to Advanced Topics
The basic json module functions covered in this lesson are the foundation for more advanced data handling in Python. As you progress, you will encounter scenarios where the default behavior needs customization — such as serializing Python objects that are not natively supported by JSON (like datetime objects or custom classes).
| This Lesson (Intro) | Advanced Topic |
|---|---|
json.dumps() with dicts/lists | Custom JSONEncoder class to serialize datetime, Decimal, custom objects |
json.loads() returns basic types | object_hook parameter to convert JSON objects into custom Python classes |
| Reading/writing local files | Consuming REST APIs with requests library — JSON is the standard response format |
Simple indent formatting | JSON Schema validation — ensuring data matches an expected structure |
| Small data files | Streaming large JSON files with ijson or line-delimited JSON (JSONL) |
How introductory json skills connect to advanced Python topics
If you continue into web development, you will discover that virtually every modern API communicates using JSON. Libraries like requests and frameworks like Flask and Django heavily rely on JSON for sending and receiving data. The skills you learn here — serializing, deserializing, reading files, writing files — transfer directly to those real-world applications.
SECTION 9
Practice Problems
Question 1: CONCEPTUAL
json.dumps() and json.dump(). Why does one function name end in s and the other does not? When would you use each one?Show answer
s stands for 'string.' json.dumps() converts a Python object into a JSON-formatted string in memory. json.dump() writes the JSON directly to a file object. You would use dumps() when you need the JSON as a string variable (for example, to print it or send it as part of an API response). You would use dump() when you want to save data to a .json file on disk.Question 2: BASIC CALCULATION
import json
data = {"temp": 72, "unit": "F", "sensors": ["A1", "B2"]}
result = json.dumps(data)
print(type(result))
print(result)Show answer
print outputs <class 'str'> because json.dumps() always returns a string, not a dictionary. The second print outputs the JSON string: {"temp": 72, "unit": "F", "sensors": ["A1", "B2"]}. Notice that while this looks similar to the Python dictionary, it is now a single string of text. The quotes around keys and string values use double quotes, which is required by the JSON specification (Python dictionaries accept single or double).Question 3: INTERMEDIATE
"title", "author", "year", and "genres" (a list). Save it to a file called book.json with pretty-printed indentation of 4 spaces. Then read the file back and print only the title.Show answer
import json
book = {
"title": "Ender's Game",
"author": "Orson Scott Card",
"year": 1985,
"genres": ["science fiction", "military"]
}
with open("book.json", "w") as f:
json.dump(book, f, indent=4)
with open("book.json", "r") as f:
loaded_book = json.load(f)
print(loaded_book["title"])
This prints Ender's Game. The key steps are: (1) create the dict, (2) use json.dump() with indent=4 to write to the file, (3) use json.load() to read it back, and (4) access the value with standard dictionary bracket notation.Question 4: APPLIED
weather_json = '{"city": "Austin", "temp_f": 95, "conditions": ["sunny", "humid"], "wind_mph": 8.5, "alert": null}'
Parse this string into a Python object. Then write code to (a) print whether there is a weather alert, (b) convert the temperature from Fahrenheit to Celsius using the formula C = (F − 32) × 5 ÷ 9, and (c) add the Celsius value as a new key "temp_c" and print the updated dictionary as a pretty-printed JSON string.Show answer
import json
weather_json = '{"city": "Austin", "temp_f": 95, "conditions": ["sunny", "humid"], "wind_mph": 8.5, "alert": null}'
weather = json.loads(weather_json)
# (a) Check alert
if weather["alert"] is None:
print("No active weather alert.")
else:
print(f"Alert: {weather['alert']}")
# (b) Convert temp
temp_c = (weather["temp_f"] - 32) * 5 / 9
print(f"Temperature in Celsius: {temp_c:.1f}")
# (c) Add key and pretty-print
weather["temp_c"] = round(temp_c, 1)
print(json.dumps(weather, indent=2))
The JSON null becomes Python None, so we check is None. The temperature converts to approximately 35.0 °C. We add it as a new key before serializing the updated dictionary back to a formatted JSON string.Question 5: CRITICAL THINKING
TypeError:
import json
scores = {"math": 92, "english": 88}
frozen = frozenset([1, 2, 3])
data = {"scores": scores, "ids": frozen}
print(json.dumps(data))
Explain (a) why the error occurs, (b) what Python types the json module cannot serialize by default, and (c) propose two different approaches to fix the code so it produces valid JSON.Show answer
frozenset is not one of the types the json module knows how to serialize. JSON only supports objects, arrays, strings, numbers, booleans, and null. Python's frozenset (and set) have no direct JSON equivalent.
(b) Types the json module cannot serialize by default include: set, frozenset, datetime objects, bytes, custom class instances, and Decimal objects.
(c) Fix 1 — Convert the frozenset to a list before serializing: data = {"scores": scores, "ids": list(frozen)}. Fix 2 — Use the default parameter: json.dumps(data, default=list). The default parameter specifies a function that is called for objects that are not normally serializable. Passing list tells it to try converting any unknown type to a list.SUMMARY
Lesson Summary
Summary
Python's json module provides a simple, built-in way to convert between Python objects (dictionaries, lists, strings, numbers, booleans, and None) and JSON text. The process of converting Python to JSON is called serialization, and the reverse is deserialization. There are exactly four core functions to remember: json.dumps() produces a JSON string, json.dump() writes to a file, json.loads() parses a string, and json.load() reads from a file.
Key details to remember: functions ending in s work with strings; functions without s work with files. The indent parameter makes output human-readable. Python True/False become JSON true/false, and Python None becomes JSON null. Tuples are converted to arrays (and come back as lists). Not all Python types are serializable — sets, custom objects, and datetime must be converted manually. These fundamentals prepare you for working with web APIs, configuration files, and data persistence in any Python project.