Studio Matrx Monthly · Volume 1 · Issue 3 · August 2026
Amogh N P
 In loving memory of Amogh N P — Architect · Designer · Visionary 
CSV & JSON DataLesson 3.4
PSD for Architecture, Planning & Urban Design/Module 3 · Functions, Modules & Files

Lesson 3.4 · Functions, Modules & Files

CSV & JSON Data

Schedules, exports and settings live as CSV and JSON - two formats every designer meets and both easy to read in Python

13 min Interactive lessonFree · open lessonByAmogh N P· Architect & interior designer
The hook

Every schedule you export and every settings file you touch is CSV or JSON. Two small modules read both - and suddenly your scripts speak the language of real design data.

Loose text files got you started, but real design data has structure. A room schedule is a table of rows and columns. A material library or a set of project settings is a tree of named values, some nested. Two formats carry almost all of it: CSV (comma-separated values - flat, spreadsheet-like) and JSON (JavaScript Object Notation - nested and richer).

Python reads and writes both with two small standard-library modules, csv and json, and nothing to install. This lesson shows you how to pull a schedule out of a CSV, hand structured data to and from JSON, and - just as important - choose which format fits a given job. It is where the file plumbing of the last lesson becomes genuinely useful.

CSV = table (DictReader/DictWriter). JSON = tree (load/dump). Both standard library, both plain text.

Two formats, two shapes of data

Before any code, get the mental picture, because choosing right saves hours. CSV is a table: the first line is usually a header of column names, and every line after is one record with values separated by commas. It maps exactly onto a spreadsheet, which is why every schedule tool and BIM export offers 'export to CSV'. JSON is a tree: it stores named values ("area": 18.0), lists (["oak", "linen"]) and nested objects, so it can hold richer, hierarchical data that a flat table cannot.

A rough rule you can lean on: if your data is rows that all share the same columns - a room list, a door schedule, a BOQ - reach for CSV. If it is nested or mixed - a project's settings, a material with a list of finishes and a supplier object, anything tree-shaped - reach for JSON. Both are plain text you could open in an editor and read, which is part of why they have lasted: no proprietary format, no lock-in, human-inspectable, and readable by nearly every tool. Understanding which shape your data really has is half the skill; the modules that read them are the easy other half.

It helps to know why these two formats, of all the possibilities, are the ones you keep meeting. Both are open - no company owns them, no licence is needed, and any tool can read and write them - which is why they became the common tongue between programs that otherwise share nothing. Both are also human-readable: open either in a text editor and you can see exactly what is there, which makes debugging a data problem a matter of looking rather than guessing. CSV predates the personal computer and survives because spreadsheets everywhere speak it; JSON grew up with the web and is now the default way apps and services exchange data. For a designer, the practical consequence is that learning these two formats is not learning a niche skill - it is learning the language your BIM exports, your spreadsheets, and the web APIs of Module 8 all already speak.

CSV = TABLE JSON = TREECSV - rows & columnsroom,area,floorliving,18.0,1kitchen,12.0,1bedroom,14.0,2Flat, spreadsheet-like,one record per line.JSON - nested tree{"room": "living", "area": 18.0, "finishes": [ "oak", "linen"]}Nests lists and objects,good for rich structure.Flat schedule? Reach for CSV. Nested settings or mixed data? Reach for JSON.
Zoom
The two shapes of structured data designers meet: CSV is a flat table of rows sharing the same columns - a schedule or BOQ - while JSON is a nested tree of named values and lists, holding richer structure a table cannot. Matching the format to the shape of your data is half the skill.

CSV = flat table, shared columns. JSON = nested tree of named values and lists. Both plain text.

Reading a schedule with the csv module

You could read a CSV by splitting each line on commas yourself, but that breaks the moment a value contains a comma. The csv module handles the fiddly rules for you. Its DictReader is the designer's friend: it reads the header row and hands you each record as a dictionary keyed by column name:

python
import csv

total = 0.0
with open("rooms.csv", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        area = float(row["area"])    # values come in as text
        total += area
        print(row["room"], area)

print(f"Total area: {total} m2")

Each row is a dict like {"room": "living", "area": "18.0", "floor": "1"}, so you grab fields by name - row["area"] - which stays readable even with many columns. Two details to bank: pass newline="" when opening a CSV (it prevents blank-line glitches on some systems), and remember every value arrives as a string, so wrap numbers in float() or int() before doing maths. That single loop - open, DictReader, pull fields by name, convert, accumulate - is the workhorse for totalling a BOQ, filtering a schedule, or checking an export.

The same loop does far more than total a column. Because each row is a dictionary, you can filter (if row["floor"] == "2"), group, spot problems, or check for missing data - a genuinely useful quality-control move on real exports, where a blank area or a mistyped room name is exactly the kind of error a script catches instantly and the eye misses. A quick validity pass might collect every row where row["area"] is empty or does not convert to a number, and print them for you to fix at source. There is also a plainer csv.reader that hands you each row as a simple list rather than a dict; it is fine when a file has no header, but DictReader is almost always nicer because reading row["area"] tells you what you are grabbing where row[3] makes you count columns. Reach for DictReader by default, and keep reader in mind only for headerless files.

CSV -> PYTHON -> JSONrooms.csva schedulePythonlist of dicts:clean, filter, totalout.jsonfor an app / APIRead with csv.DictReader, work as plain dicts, hand off with json.dump. A tiny, reusable pipeline.
Zoom
A tiny, reusable pipeline: read a CSV schedule with csv.DictReader into a list of plain Python dicts, clean, filter and total it in ordinary code, then hand it off as JSON with json.dump for an app or API. The same open-and-loop foundation from the last lesson, now speaking structured data.

csv.DictReader gives each row as a dict keyed by column. Values are strings - float()/int() them.

Writing CSV back out

Producing a clean CSV is just as direct, and it is how your script hands results to a spreadsheet or another tool. DictWriter is the mirror of DictReader: you tell it the column names, write the header, then write each row as a dict:

python
import csv

rooms = [
    {"room": "living", "area": 18.0},
    {"room": "kitchen", "area": 12.0},
]

with open("out.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["room", "area"])
    writer.writeheader()
    writer.writerows(rooms)

Open the resulting out.csv in Excel or Google Sheets and it is a proper two-column table. This closes a genuinely useful loop: read a messy export in with DictReader, clean or filter or total it in plain Python, and write a tidy CSV back out with DictWriter - a schedule your team can open without ever knowing a script touched it. Because CSV is universal, this is often the most practical way to deliver results: not a fancy app, just a clean spreadsheet file that slots into everyone's existing workflow. Keep the fieldnames list and your row dictionaries using the same keys and the two halves fit together cleanly.

A few practical points make CSV writing reliable. Use newline="" in the open() call for writing just as you did for reading - it stops an extra blank line appearing between rows on some systems, a small glitch that puzzles people the first time. If a dictionary is missing one of the declared fieldnames, DictWriter writes an empty cell rather than crashing, which is forgiving but worth knowing so blanks do not surprise you. And the fieldnames list also fixes the column order of the output, so you control how the spreadsheet reads left to right. Because the result is an ordinary CSV, it drops straight into whatever your colleagues already use - no plugin, no import wizard, just a file they double-click. That is often the quiet win of scripting in a practice: not a shiny tool, but a clean, correct spreadsheet produced in a second that would have taken an afternoon by hand, handed over in a format everyone already trusts.

csv.DictWriter: set fieldnames, writeheader(), writerows(). Out comes a real spreadsheet.

JSON: nested data in and out

When data is nested rather than tabular, JSON is the natural fit, and the json module makes the round trip almost trivial. It maps neatly onto Python: JSON objects become dicts, arrays become lists, and the rest becomes strings, numbers, booleans and None. Four functions cover it - load/dump work with files, loads/dumps with strings:

python
import json

project = {
    "name": "Riverside Flat",
    "rooms": ["living", "kitchen", "bedroom"],
    "finishes": {"floor": "oak", "walls": "linen white"},
}

with open("project.json", "w") as f:
    json.dump(project, f, indent=2)      # write, nicely indented

with open("project.json") as f:
    loaded = json.load(f)                # read it back as a dict

print(loaded["finishes"]["floor"])       # oak

Notice how a JSON file preserves the structure - the list of rooms and the nested finishes object survive the round trip intact, unlike a flat CSV which would have to flatten them. The indent=2 argument pretty-prints the file so a human can read and diff it. Because JSON is the language of web APIs and countless config files, json.load and json.dump are also exactly the functions you will reach for in Module 8 when you start pulling data from the web. Getting comfortable with this now means structured data holds no fear later.

The file-versus-string distinction is the one thing to fix in memory: the plain names load and dump work with a file object, while the s-suffixed loads and dumps work with a string (the s stands for string). You will use dumps to turn data into a string for printing or sending, and loads to turn a string received from a web API back into a dict - which is precisely the Module 8 use. A couple of honest limits keep you out of trouble: JSON can hold strings, numbers, booleans, lists, nested objects and null, but not arbitrary Python objects like a datetime or a set - those you convert to a string or list first. And a JSON object's keys are always strings, so a dictionary with number keys comes back with string keys after a round trip. These are minor once you know them, and in return you get a format that preserves rich, nested structure perfectly and is understood by virtually every language and service on earth.

json.dump/load for files, dumps/loads for strings. JSON objects <-> dicts, arrays <-> lists.

Choosing the right format

With both tools in hand, the real skill is picking well. Ask what shape your data is and who receives it. CSV wins when data is a flat table with consistent columns and a human on the other end will likely open it in a spreadsheet - schedules, BOQs, quantity lists, exports for a client or contractor. It is compact, universal and effortless in Excel. JSON wins when data is nested, mixed or hierarchical, when structure must be preserved exactly, or when another program (an app, a web API, a config-driven tool) will read it - project settings, a material library, anything tree-shaped.

When they overlap, let the destination decide: a spreadsheet-bound deliverable leans CSV, a program-bound one leans JSON. And it is common to convert between them - read a CSV schedule, enrich each row with nested data, and write JSON for an app, which is exactly the little pipeline the figure shows. Both are plain-text, standard-library, install-nothing formats, so you can move fluidly between them. Master these two and you can exchange data with virtually any design tool, spreadsheet or service - which is what turns an isolated script into part of a real workflow.

Flat table for humans -> CSV. Nested data for programs -> JSON. When unsure, follow the destination.

Terms & tools you'll meet in this lesson

csv module

Reading and writing comma-separated tables correctly

Standard library; handles quoting and delimiters that naive string splitting gets wrong.

csv.DictReader

Reading each CSV row as a dict keyed by column name

Readable field access by header name; remember values arrive as strings - convert with float/int.

csv.DictWriter

Writing dicts back out as a CSV table

Set fieldnames, writeheader(), then writerows() - produces a file any spreadsheet opens.

json module

Reading and writing nested JSON data

load/dump for files, loads/dumps for strings; JSON objects map to dicts, arrays to lists.

CSV vs JSON

Flat table versus nested tree

CSV for spreadsheet-shaped data and human recipients; JSON for nested structure and programs.

Hands-on workshop

Workshop - read a CSV schedule, write JSON

You will read a room schedule from a CSV, total the areas, and write an enriched JSON file - the small but genuinely useful CSV-to-JSON pipeline in full.

Python 3 only - csv and json are both standard library. A spreadsheet app is handy to inspect the CSV.

Given & goal
Goal: read a CSV, transform it, write JSON
Inputs: a rooms.csv you create with room,area,floor columns
Time: ~40 minutes
  1. 1Create rooms.csv with a header line room,area,floor and a handful of rows, saved next to your script.
  2. 2Read it with csv.DictReader inside a with open(..., newline='') block; loop the rows, convert row['area'] to float, and print each room with its area.
  3. 3While looping, accumulate a running total of area and count the rooms; after the loop, print the total and the count.
  4. 4Build a Python dictionary that holds the project name, the list of rooms (each as a small dict), and a summary block with the total area and room count.
  5. 5Write that dictionary to project.json with json.dump(..., indent=2), then read it back with json.load and print one nested value to prove the round trip worked.

You’ll walk away with
Your rooms.csv, the script, and the generated project.json - plus a one-line note on why you chose JSON for the output rather than another CSV.

The worked example

Three altitudes on the same idea

Read the band that fits you — or all three.

For the architectAutomate busywork & build custom tools

CSV and JSON are how your scripts exchange data with the rest of the toolchain. Revit, spreadsheets and most schedule tools export CSV, so reading one to total areas, check for missing data or filter a door list is immediately useful - and writing a clean CSV back gives your team a schedule they can open anywhere. JSON, meanwhile, is how settings and richer project data move between apps and the web services Module 8 reaches.

For the interior designerScripts for data, schedules & layouts

Your FF&E and finishes schedules are CSV waiting to be scripted. Read a supplier's export with csv.DictReader, apply your markup or wastage, total the quantities, and write a tidy CSV back for the client - all without retyping a cell. When a material carries nested detail - variants, a list of finishes, a supplier block - JSON keeps that structure intact where a flat spreadsheet would lose it.

For the studentA hireable computational skill

These two formats are the data currency of real projects, so employers assume you can handle them. Reading a CSV schedule and writing JSON is a small, concrete skill that shows up constantly in computational-design and BIM work. Practise the DictReader loop and the json.load / json.dump round trip until they are second nature - Module 4's pandas builds directly on the same CSV-reading foundation.

Misconception check

CSV is just text split on commas, so I do not need a special module - I will split each line myself.

It looks that simple and it is a trap. Real CSV files are full of edge cases that naive splitting mangles: a value containing a comma is wrapped in quotes ('"Kitchen, main"'), values can contain quotes or line breaks, and different tools use different delimiters and encodings. Splitting on commas by hand works on your neat example and then silently corrupts the first real export with an address or a description in it. The csv module implements the actual CSV conventions, handling quoting and escaping correctly, and DictReader additionally maps each row to column names for readable code. It is standard library, so there is nothing to install and no reason to reinvent it. Reach for csv every time, even when the file looks trivially simple - the file you get next week will not be.
Try it

Do it yourself

Predict each answer, then run to confirm.

  1. 1When would you choose CSV over JSON, and when the reverse?
  2. 2What does csv.DictReader give you for each row, and why is that easier than splitting on commas?
  3. 3After reading a CSV, why must you often call float() or int() on a value before doing maths?
  4. 4Which json functions work with files and which with strings?
  5. 5What does JSON preserve that a flat CSV cannot - give a concrete example?
Take this with you

The one line to carry out

CSV is a flat table you read with csv.DictReader and write with csv.DictWriter; JSON is a nested tree you load and dump with the json module - choose CSV for spreadsheet-shaped data and people, JSON for nested data and programs. Both are standard library, plain text, install nothing.
Take it further
References & further reading

Peer-reviewed journals & authoritative standards

  1. 01Comma-separated valuesWikipedia, 2026.
  2. 02JSONWikipedia, 2026.
  3. 03csv - CSV File Reading and WritingPython Software Foundation, 2026.
  4. 04json - JSON encoder and decoderPython Software Foundation, 2026.
Related lessons
Recap
Real design data is structured, and two plain-text formats carry most of it. CSV is a flat table read with csv.DictReader (each row a dict keyed by column, values arriving as strings) and written with csv.DictWriter. JSON is a nested tree handled by the json module - load/dump for files, loads/dumps for strings - mapping objects to dicts and arrays to lists, and preserving structure a flat table cannot. Choose CSV for spreadsheet-shaped data and human recipients, JSON for nested data and programs, and convert between them freely.
Carry forward →

You can now move structured data in and out of files by hand. Module 4 hands that same CSV to pandas, which turns a whole schedule into an analysable table you can filter, total and chart in a line or two - the same data, far more power.

A

The author

Amogh N P

Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.

More about Amogh →