LEARN PYTHON | Csv Files And Json Data

Lesson objective

Read and write CSV rows and JSON structures, distinguish decoding from validation and preserve field boundaries and types deliberately.

Learn

05.2 | CSV FILES AND JSON DATA

01 | STRUCTURE NEEDS MORE THAN A TEXT LINE

Suppose an expense has a date, category, amount and note. A single line of text could hold them, but how does a later program know where each field ends? A note might itself contain a comma. A standard format provides rules for boundaries and escaping.

CSV suits tabular records with columns. JSON suits nested combinations of lists and objects. Both are text formats, so you can inspect them in an editor, but neither automatically establishes that an expense is true or valid.

Choose based on the intended use. The project uses JSON for its saved record list and CSV for a readable export. It does not import that export back into the tracker.

02 | CSV USES ROWS AND FIELDS

CSV stands for comma-separated values, although variants may use other delimiters. A row has fields in column order. A header row can label those columns. When a field contains a delimiter, quotation marks or line break, quoting rules preserve it as one field.

Do not parse general CSV with line.split(","). The line date,food,2.50,"Lunch, drink" includes a comma inside one note. A CSV parser understands the quotes and gives four fields rather than five.

Python’s csv module reads and writes these rules. Open CSV files with newline="" so the module can manage line endings correctly, including newline characters within quoted fields.

import csv

with open("expenses.csv", "w", encoding="utf-8", newline="") as file:
    writer = csv.writer(file)
    writer.writerow(["date", "category", "amount", "note"])
    writer.writerow(["2026-10-01", "food", "2.50", "Lunch, drink"])

with open("expenses.csv", "r", encoding="utf-8", newline="") as file:
    for row in csv.reader(file):
        print(row)

EXPECTED OUTPUT

['date', 'category', 'amount', 'note']
['2026-10-01', 'food', '2.50', 'Lunch, drink']

03 | CSV FIELDS ARE USUALLY TEXT

The ordinary CSV reader returns strings for fields. It does not infer that 2.50 means a currency amount or that a date is a real calendar day. Decide conversions and validation after parsing.

DictReader uses the header values as dictionary keys. That makes row["amount"] clearer than guessing a column index, but the header must still match the expected schema. Duplicate names, missing columns and unexpected fields need explicit checks in a robust importer.

DictWriter accepts dictionaries and a fieldnames sequence defining output columns. writeheader() creates the labels. Normal rows can then be written without manually escaping every note.

import csv

with open("people.csv", "w", encoding="utf-8", newline="") as file:
    writer = csv.DictWriter(file, fieldnames=["name", "score"])
    writer.writeheader()
    writer.writerow({"name": "Maya", "score": 8})

with open("people.csv", encoding="utf-8", newline="") as file:
    row = next(csv.DictReader(file))
    print(row["name"], repr(row["score"]))

EXPECTED OUTPUT

Maya '8'

04 | JSON STORES NESTED DATA

JSON means JavaScript Object Notation, but Python and many other languages use it. A JSON object resembles a Python dictionary with string keys; an array resembles a list. JSON has strings, numbers, true, false and null.

In Python, the json module maps ordinary JSON objects to dictionaries, arrays to lists, true and false to Boolean values, and null to None. JSON source uses double quotes for strings and its own literal spellings. It is not a Python expression.

Do not use eval() to load a data file. json.load parses JSON data rather than executing arbitrary Python instructions. Parsing is still separate from checking the expected fields, types and permitted values.

import json

text = '{"name": "Maya", "scores": [8, 10], "finished": true, "comment": null}'
record = json.loads(text)
print(record["name"])
print(record["scores"][1])
print(record["finished"], record["comment"])

EXPECTED OUTPUT

Maya
10
True None

05 | LOAD AND DUMP USE FILES

json.dump writes a Python value to an open text file as JSON. json.load reads one JSON document from a file. The related dumps and loads functions work with strings: the final s can remind you that these versions produce or consume a string.

indent=2 formats the document for human inspection. ensure_ascii=False allows characters such as é to appear directly when the file encoding supports them. Neither option changes the application meaning of the record.

Write one complete document. Appending a second JSON list after the first does not extend the existing list; it creates multiple adjacent documents that ordinary json.load rejects.

import json

records = [{"name": "Maya", "scores": [8, 10]}]
with open("records.json", "w", encoding="utf-8") as file:
    json.dump(records, file, ensure_ascii=False, indent=2)
with open("records.json", "r", encoding="utf-8") as file:
    restored = json.load(file)
print(restored == records)

EXPECTED OUTPUT

True

06 | KNOW WHAT A ROUND TRIP PRESERVES

A round trip writes data and reads it back. Ordinary lists, string-keyed dictionaries and JSON-compatible values can preserve the intended structure. A tuple becomes a JSON array and reads back as a list. Sets do not directly serialize with the default encoder.

JSON object keys are strings. Avoid assuming integer-keyed dictionaries return with the same key types. Dates need an agreed representation such as an ISO-formatted string.

JSON syntax alone does not enforce a record schema. {"amount_cents": "250"} is valid JSON but stores text instead of the integer the tracker needs. Validate after decoding before using it in calculations.

07 | MONEY NEEDS A REPRESENTATION RULE

Binary floating-point values are useful for many measurements, but decimal money arithmetic can expose representation rounding. Formatting to two decimal places only changes displayed text; it does not make the stored float exact.

The project uses whole-number cents in one currency. CHF 2.50 becomes integer 250. Adding 10 and 20 cents gives exactly 30 cents under integer arithmetic. The input rule accepts a positive amount with at most two decimal places; it does not silently round a third decimal.

A mature financial application may use Decimal and additional accounting rules. Here, integer cents keeps one clear learning contract. Mixing currencies without conversion would still make a total meaningless, so the tracker explicitly uses CHF only.

amounts_cents = [10, 20, 250]
total = sum(amounts_cents)
print(f"CHF {total // 100}.{total % 100:02d}")

EXPECTED OUTPUT

CHF 2.80

08 | INSPECT A JSON RECORD

Edit the JSON below and ask the model to decode it. Then it separately checks a small demonstration schema. Successful syntax decoding does not automatically mean the shape or values fit that schema.

09 | FAIL CLEARLY ON DAMAGED DATA

Malformed JSON raises JSONDecodeError. An unreadable file can raise OSError or a decoding exception. A syntactically valid but unsuitable record needs a separate validation error. Keep these different failures visible enough to diagnose.

For the project, a missing save file starts a new list. An existing corrupted file stops startup and stays available for inspection. Treating every failure as [] risks replacing evidence of earlier expenses with an empty dataset.

JSON and CSV are formats, not databases with automatic transactions, access controls or multi-user coordination. The project is a small local program for one process, which keeps the scope manageable.

10 | TEST THE FORMAT WITH AWKWARD TEXT

Use a note containing a comma, quotation marks and a Unicode character. Save and reload it using the proper module. Check exact field values, not merely whether the output looks plausible.

For JSON, test a list of records, an empty list, malformed text and valid text with the wrong root type. For CSV, verify the header and that a quoted comma remains inside one note.

A file extension is a label, not proof of its contents. A file called expenses.json may contain invalid JSON. Trust the parser and your schema checks rather than the name alone.

PUT YOUR SKILLS TO WORK

Use the Section 5 challenges to practise these ideas independently. Work in your Python editor, predict results and keep a short test record.

Section 5 challenges Python course navigation

MATCH THE PYTHON TERM TO ITS MEANING

Terminology

Terminology

CSV

A tabular text format with delimiter and quoting rules.

Delimiter

A character separating fields in a defined format.

Field

One value in a tabular row or record.

Header

A row of column labels.

Quoting

A format rule preserving delimiters or other special characters inside a field.

csv.reader

A reader yielding parsed CSV rows as lists of fields.

DictReader

A CSV reader mapping header names to field values.

DictWriter

A CSV writer using dictionaries and declared field names.

JSON

A text format representing objects, arrays and scalar values.

Serialization

Converting data into a representation suitable for storage or transfer.

Deserialization

Reconstructing data from its stored or transferred representation.

json.dump

Writing a JSON document to a file object.

json.load

Reading a JSON document from a file object.

json.dumps

Creating a JSON string from a Python value.

json.loads

Decoding a JSON string into a Python value.

Schema

The required shape, fields and types of application data.

Round trip

Writing data and reading it back to check preservation.

Integer cents

A whole-number representation of hundredths of one currency unit.

Questions

Questions

CHECK YOUR UNDERSTANDING

Select all correct choices. Each exact set earns one point.

1. Why is split(",") unsuitable for general CSV?
2. What type does an ordinary csv reader produce for field 2.50?
3. Which setting is recommended when opening CSV files for the csv module?
4. Which JSON-to-Python mappings are correct?
5. Which function reads JSON from an open file?
6. A JSON document decodes successfully. What still needs checking?
7. What happens to a tuple after ordinary JSON encoding and decoding?
8. Why use integer cents in this project?

EXPLAIN AND COMPARE

Write your answers before revealing each sample.

1. Explain why general CSV needs a parser.

2. Compare CSV and JSON for expense data.

3. Explain load versus loads.

4. Describe a schema check after decoding.

5. Explain a tuple round-trip limitation.

6. Explain why appending JSON documents is not list extension.

7. Explain integer-cent arithmetic.

8. Design awkward-text format tests.

CODE IT | YOUR INDEPENDENT CHALLENGE

Write and reload CSV and JSON examples containing commas and Unicode. Check exact values and schema separately.

Work in your Python editor. Keep a working version, explain one design choice and record at least two tests. Use the Learn tab for worked examples before comparing your result.

Flashcards

Flashcards

Click to flip. Select the ideas you need to revisit.

0 cards selected for revision.

    Selections are kept while this page is open.

    Workbook

    Workbook

    COMING SOON

    The workbook for Csv Files And Json Data is coming soon. Complete the matching task and written questions in your exercise book.