Working with Data
🗃️ Working with Data
json module for JSON data, the csv module for spreadsheet-style data, and a deeper look at datetime, which you saw briefly in Course 1, Chapter 9.
📋 JSON
JSON's types map onto Python's fairly directly: JSON objects become dicts, arrays become lists, true/false become True/False, and null becomes None. dumps/loads (with an "s", for "string") convert to and from a Python string; dump/load (no "s") read and write a file directly.
JSON only understands strings, numbers, booleans, null, objects, and arrays — a Python date object (or any other custom type) has no direct JSON equivalent. The fix is to convert it to a string first (e.g. str(datetime.date.today()) or .isoformat()) before serializing, or pass a custom default= function to json.dumps() that tells it how to convert non-standard types.
📊 CSV
DictReader/DictWriter use the file's header row as dictionary keys — usually more convenient than reader/writer's plain lists, since you access columns by name (row["score"]) instead of by position (row[1]), the same readability trade-off dicts always have over lists.
📅 The datetime Module, Deeper
strftime ("string format time") turns a datetime into a string using a format code like %Y-%m-%d; strptime ("string parse time") does the reverse, turning a string into a datetime given the format it's in. Adding/subtracting a timedelta — as briefly seen with subtraction in Course 1's own challenge solutions — handles date arithmetic without manually accounting for month lengths or leap years.
Structured Data Serialization: Go vs Kotlin vs Python
| Language | Approach |
|---|---|
| Go | encoding/json maps JSON onto real, statically-typed struct fields using json:"field_name" struct tags — the shape is declared and checked at compile time. |
| Kotlin | kotlinx.serialization (or Gson/Jackson) similarly maps JSON onto typed data class fields, checked by the compiler. |
| Python | json.loads() returns a plain, untyped dict — no schema is declared or checked; a missing or misspelled key only fails at runtime, as a KeyError. |
This is a real trade-off worth noticing coming from Go or Kotlin: Python's approach is faster to write and more flexible, but loses the compile-time guarantee that the JSON actually matches the shape your code expects.
json.dumps/loads
Python dict/list ⟷ JSON string; dump/load for files directly.
csv.reader/writer
Rows as plain lists; DictReader/DictWriter for rows as dicts by column name.
strftime / strptime
Format a datetime to a string, or parse a string into a datetime.
timedelta
Date/time arithmetic that correctly handles month lengths and leap years.
💻 Coding Challenges
Challenge 1: Round-Trip a Dict Through JSON
Given a dict representing a small product (name, price, in_stock), convert it to a JSON string with json.dumps(), then parse that string back into a Python dict with json.loads(), and confirm the round trip produced an equal dict.
Goal: Practice the full dumps → loads round trip and confirm no data was lost.
Challenge 2: CSV Average Score
Given a CSV file with columns name and score, use csv.DictReader to read every row and calculate the average score across all students (remembering that CSV values are read as strings, so each score needs converting to a number first).
Goal: Practice DictReader combined with numeric type conversion, a common real-world CSV gotcha.
Challenge 3: Days Until a Parsed Deadline
Given a deadline as a string, "2026-12-25", use datetime.strptime() to parse it into a date, then calculate and print how many days remain between today and that date.
Goal: Practice strptime parsing combined with date subtraction.
🎯 What's Next
Next chapter: Testing with pytest — assertions, fixtures, parametrize, and a contrast with the built-in unittest module.