COMPUTER PROGRAMMING 1 (PYTHON) • PROBLEM SOLVING & MINI-PROJECTS

Building JSON Address Book — I can build a simple JSON-based address book (list of dicts) with lookup and update at my level.

Learn to store, search, and update contact information using Python lists, dictionaries, and JSON files.

Historical Context & Motivation

People have been keeping address books for centuries — handwritten ledgers full of names, addresses, and phone numbers. As computers became mainstream, the challenge shifted to figuring out how to represent that same contact data in a format machines could understand. Early computer systems stored contacts in flat text files with rigid column widths, which made editing and searching slow and error-prone.

The invention of JSON (JavaScript Object Notation) in the early 2000s changed everything. JSON gave developers a lightweight, human-readable way to structure data using simple key-value pairs. Today, virtually every app on your phone — from your contacts list to social media — uses JSON behind the scenes to store and exchange information.

1970s
Flat File Databases
Early contact managers stored data in plain text files with fixed-width columns. Searching required reading the entire file line by line.
1990s
XML Emerges
XML provided a structured, tagged format for data, but it was verbose and difficult to read. A simple contact record could be dozens of lines long.
2001
JSON Is Born
Douglas Crockford popularized JSON as a lightweight data-interchange format. Its simple syntax — curly braces for objects and square brackets for arrays — made it immediately accessible.
2010s
JSON Becomes Universal
JSON became the default format for web APIs, mobile apps, and configuration files. Python added built-in support through its json module.
Today
JSON Everywhere
From phone contacts to cloud databases, JSON structures underpin nearly every modern application you interact with daily.

The core question this lesson addresses is straightforward: how do you organize a collection of contacts in Python so you can save them to a file, look someone up quickly, and update their information? By building a JSON-based address book, you'll master the practical combination of lists, dictionaries, and file I/O that appears in real-world software every day.

Core Principles & Definitions

Before we start coding, let's nail down the foundational ideas that make a JSON address book work. Each concept builds on Python data structures you've already seen — lists and dictionaries — and connects them to the JSON file format for persistent storage.

1

Dictionary as a Contact Record

A Python dictionary (dict) maps keys like "name", "phone", and "email" to their values. Each dict represents one person's contact information.
2

List of Dicts as the Address Book

A Python list holds all your contact dictionaries in one ordered collection. You can loop through it, search it, or add new entries at any time.
3

JSON for Persistence

JSON (JavaScript Object Notation) is a text-based file format that mirrors Python's lists and dicts almost perfectly. Python's json module converts between Python objects and JSON files with just a few lines of code.
4

Lookup — Finding a Contact

Lookup means iterating through the list of dicts and checking whether a specific key (like "name") matches the value you're searching for. This is a linear search through the collection.
5

Update — Modifying a Contact

Update means finding the right dict in the list and changing one or more of its values. Because dicts are mutable, you can reassign any key's value directly.
✦ KEY TAKEAWAY
Think of a JSON address book like a filing cabinet. Each dictionary is a single contact card with labeled fields (name, phone, email). The list is the drawer that holds all the cards in order. And the JSON file is the cabinet itself — it keeps your data safe on disk even after you close the program.

Visual Explanation — Data Structure Map

The diagram below shows how a Python list of dictionaries maps directly to JSON syntax. Notice how Python's [] brackets become JSON arrays and Python's {} braces become JSON objects. The structure is nearly identical, which is why Python's json module can convert between them so easily.

The left side shows a Python list containing three dictionaries in memory. The green arrows represent json.dump() (writing to disk) and json.load() (reading from disk). The right side shows the resulting contacts.json file. Notice the nearly identical syntax.

The key insight from this diagram is that Python dicts and JSON objects share the same structure: curly braces wrapping key-value pairs. Likewise, Python lists and JSON arrays both use square brackets to hold ordered collections. This natural mapping is what makes Python's json module so convenient — you don't need to write any custom parsing code.

How It Works — The Core Operations

Every address book application relies on four fundamental operations, sometimes called CRUD: Create, Read, Update, and Delete. In this lesson we'll focus on three of those — creating contacts, looking them up (reading), and updating their data. Let's walk through the code patterns for each operation.

Creating the Address Book & Adding Contacts

You start by importing the json module and defining an empty list. Each time you want to add a contact, you build a dictionary with the appropriate keys and append it to the list. Here is the pattern:

💻 Code Pattern — Add a Contact
import json address_book = [] def add_contact(book, name, phone, email): contact = { "name": name, "phone": phone, "email": email } book.append(contact) add_contact(address_book, "Alice Smith", "555-0101", "alice@mail.com") add_contact(address_book, "Bob Jones", "555-0202", "bob@mail.com")

Looking Up a Contact

A lookup searches through the list for a dictionary whose "name" key matches the search term. We use a for loop that returns the matching dict, or None if no match is found. This is a linear search — it checks each contact one by one, which works well for small-to-medium address books.

🔍 Code Pattern — Lookup
def lookup_contact(book, name): for contact in book: if contact["name"].lower() == name.lower(): return contact return None result = lookup_contact(address_book, "alice smith") if result: print(result["phone"]) # Output: 555-0101 else: print("Contact not found.")

Updating a Contact

An update combines the lookup step with direct dictionary assignment. Once you find the right contact, you simply reassign the value for any key you want to change. Because Python dicts are mutable (changeable in place), the modification applies immediately to the list without needing to remove and re-add the entry.

✏️ Code Pattern — Update
def update_contact(book, name, field, new_value): contact = lookup_contact(book, name) if contact: contact[field] = new_value return True return False update_contact(address_book, "Alice Smith", "phone", "555-9999")

Saving & Loading with JSON

💾 Code Pattern — Save & Load
def save_book(book, filename="contacts.json"): with open(filename, "w") as f: json.dump(book, f, indent=2) def load_book(filename="contacts.json"): with open(filename, "r") as f: return json.load(f) save_book(address_book) loaded = load_book() print(loaded[0]["name"]) # Output: Alice Smith

The json.dump() function serializes (converts) your Python list into JSON text and writes it to a file. The indent=2 argument makes the output human-readable with nice formatting. The json.load() function does the reverse — it reads the file and deserializes (converts back) the JSON text into a Python list of dictionaries.

Data Flow & Program Architecture

Now that you understand each individual operation, let's zoom out and look at how these pieces fit together into a complete program. The diagram below shows the typical flow of a menu-driven address book application. The user picks an action, the program performs it, and then loops back to the menu.

This flowchart shows the main program loop. The application starts by loading existing contacts from the JSON file, displays a menu, and branches based on the user's choice (Add, Lookup, or Update). After each operation, the program saves the updated data back to the JSON file and loops back to the menu.

Notice the loop structure in the diagram. The program doesn't exit after a single operation — it returns to the menu so the user can perform multiple actions in one session. This event loop pattern is extremely common in real applications. Also notice that saving happens after every change, ensuring data is never lost even if the program crashes unexpectedly.

📋 Complete Menu Loop Code
def main(): try: book = load_book() except FileNotFoundError: book = [] while True: print("\n--- Address Book ---") print("1. Add contact") print("2. Lookup contact") print("3. Update contact") print("4. Quit") choice = input("Choose an option: ") if choice == "1": name = input("Name: ") phone = input("Phone: ") email = input("Email: ") add_contact(book, name, phone, email) save_book(book) print("Contact added!") elif choice == "2": name = input("Search name: ") result = lookup_contact(book, name) if result: print(f"Name: {result['name']}") print(f"Phone: {result['phone']}") print(f"Email: {result['email']}") else: print("Not found.") elif choice == "3": name = input("Name to update: ") field = input("Field (phone/email): ") value = input("New value: ") if update_contact(book, name, field, value): save_book(book) print("Updated!") else: print("Contact not found.") elif choice == "4": print("Goodbye!") break main()

Worked Example — Full Session

Let's trace through a complete session where we create an address book, add two contacts, look one up, update a phone number, and save everything to a JSON file. Follow each step carefully to see how the data changes.

Building and Using an Address Book
1
Step 1 — Initialize the Address BookWe start by importing the json module and creating an empty list. At this point, address_book is [] — no contacts yet.
address_book = [] → empty list, length 0
2
Step 2 — Add Two ContactsWe call add_contact(address_book, "Alice Smith", "555-0101", "alice@mail.com") and then add_contact(address_book, "Bob Jones", "555-0202", "bob@mail.com"). Each call creates a new dict and appends it to the list.
address_book now has 2 entries: index 0 is Alice, index 1 is Bob.
3
Step 3 — Look Up BobWe call lookup_contact(address_book, "bob jones"). The function loops through each dict. On index 0 it checks "Alice Smith".lower() == "bob jones" → False. On index 1 it checks "Bob Jones".lower() == "bob jones" → True. It returns Bob's dict.
Returns {"name": "Bob Jones", "phone": "555-0202", "email": "bob@mail.com"}
4
Step 4 — Update Alice's Phone NumberWe call update_contact(address_book, "Alice Smith", "phone", "555-9999"). Internally, this calls lookup_contact to find Alice's dict, then sets contact["phone"] = "555-9999". Because dicts are mutable, this changes the data inside the list directly.
Alice's phone is now 555-9999 instead of 555-0101.
5
Step 5 — Save to JSONWe call save_book(address_book). This opens contacts.json in write mode and calls json.dump() with indent=2. The file now contains the updated address book in clean, formatted JSON.
File contacts.json written to disk with 2 contacts, Alice's phone updated.

Strengths, Limitations & Alternatives

A JSON-based address book is a great starting project, but it's important to understand where it shines and where it falls short. Comparing it to alternative approaches helps you appreciate what you've built and where you might go next.

Comparison of data storage approaches for contact management
CriterionJSON File (Our Approach)CSV FileSQL Database
Human-readableYes — nicely formatted with indentationYes — comma-separated rowsNo — binary format, needs special tools
Nested dataYes — dicts can contain lists or other dictsNo — flat rows onlyRequires multiple tables with joins
Search speedSlow for large data (linear search)Slow for large data (linear search)Fast — indexed queries
Setup complexityMinimal — just import jsonMinimal — import csvModerate — requires SQL knowledge
Best forSmall projects, config files, APIsSpreadsheet-like dataLarge apps with thousands of records
✦ KEY TAKEAWAY
Think of choosing a storage format like choosing a vehicle. A JSON file is like a bicycle — lightweight, easy to start using, and perfect for short trips. A SQL database is like a truck — more powerful and scalable, but it takes more effort to learn to drive. For an address book with a few hundred contacts, the bicycle is the right choice.

Connection to Advanced Concepts

The JSON address book you've built uses concepts that scale directly into professional software development. Understanding how your mini-project connects to more advanced tools will help you see where this learning path leads.

From beginner project to professional tools
What You LearnedAdvanced Version
List of dicts in memoryORM models (e.g., SQLAlchemy) that map Python objects to database rows
Linear search with a for loopDatabase indexing and SQL WHERE clauses for instant lookups
json.dump() / json.load()REST API serialization frameworks (e.g., Flask-RESTful, Django REST)
Menu-driven text interfaceWeb front-end with HTML forms, or a GUI with Tkinter or PyQt
try/except for missing fileComprehensive error handling, logging, and input validation

When you're ready for the next level, consider adding a delete function (completing CRUD), implementing input validation to reject empty names or improperly formatted emails, or even building a simple web interface using Flask. Each of these extensions uses the same structural patterns — lists, dicts, and JSON — that you've just learned.

Practice Problems

PROBLEM 1 — CONCEPTUAL
Explain in your own words why a list of dictionaries is a good data structure for an address book. Why not just use a single dictionary with names as keys?
PROBLEM 2 — BASIC CALCULATION
Write a function called count_contacts(book) that takes the address book list and returns the number of contacts it contains. Then write a call to it with an address book that has 3 entries and show the expected output.
PROBLEM 3 — INTERMEDIATE
Write a function called delete_contact(book, name) that removes a contact by name (case-insensitive). The function should return True if the contact was found and deleted, or False if no match was found. Hint: you can use a loop with an index.
PROBLEM 4 — APPLIED
You are building an address book for a school club with 50 members. You want to add an "address" field to each contact that includes street, city, state, and zip. Show how you would structure a single contact dict with this nested address, and explain what advantage JSON has over CSV for storing this kind of data.
PROBLEM 5 — CRITICAL THINKING
Your address book currently uses linear search to find contacts, checking each entry one by one. If the address book grows to 10,000 contacts, this becomes slow. Without switching to a database, propose a way to reorganize the data structure in Python so that looking up a contact by name is much faster. What trade-off would this introduce when adding new contacts or handling duplicate names?

Summary

In this lesson, you built a complete JSON-based address book using Python. You learned that a dictionary represents a single contact with key-value pairs like name, phone, and email. A list of dictionaries serves as the full address book, holding all contacts in an ordered collection. The json module provides json.dump() and json.load() to save data to disk and load it back, giving your program persistence across sessions.

You implemented three core operations: adding contacts by appending dicts to the list, looking up contacts with a case-insensitive linear search, and updating contacts by finding the right dict and reassigning its values. You also structured the whole program around a menu-driven loop — the same pattern used in real-world applications. These skills form the foundation for more advanced projects involving databases, web APIs, and graphical interfaces.

Varsity Tutors • Computer Programming 1 (Python) • Building JSON Address Book