JSON: збереження structured data

Повертаємось до Python.
У попередній лекції ти вивчив modules and imports.
Твої programs навчилися split code into multiple files.
Ти писав projects like:
main.py
tasks.py
safe_input.py
Дуже добре.
Твій code тепер more organized.
Менше giant file.
Менше code lasagna.
Менше “де я поклав ту function?”
Excellent progress.
Але тепер маємо іншу проблему.
У попередніх лекціях ми saved data in plain text files.
Наприклад:
Anna,anna@example.com,123456
Marco,marco@example.com,987654
This works.
Але це не perfect.
What if data becomes more complex?
What if one contact has more fields?
What if you want to save a list of dictionaries?
What if user writes a comma in the name?
Chaos.
Text files useful.
Але для structured data, JSON is better.
JSON дозволяє save data like this:
contact = {
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
into a file.
Потім можна load it back later.
Це дуже important.
JSON used everywhere.
APIs.
Web apps.
Configuration files.
Databases.
Frontend and backend communication.
Tiny scripts that accidentally become real software.
Very useful.
Very practical.
Very Python-friendly.
Що ти вивчиш
У цій лекції ти вивчиш:
- що таке JSON;
- чому JSON useful;
- як виглядає JSON;
- чому JSON similar to Python dictionaries and lists;
- як import
jsonmodule; - як save data with
json.dump(); - як load data with
json.load(); - як save a dictionary;
- як save a list of dictionaries;
- як format JSON nicely with
indent; - як handle missing JSON files;
- як build contact book using JSON;
- типові beginner mistakes with JSON.
До кінця цієї лекції твої programs зможуть save structured data properly.
Не просто simple lines.
Real data.
Lists.
Dictionaries.
Nested information.
Very powerful.
Very useful.
Very “now this is starting to look like a real app”.
Що таке JSON?
JSON means:
JavaScript Object Notation
Не панікуй.
Even though name says JavaScript, JSON is used by many languages.
Python uses JSON.
JavaScript uses JSON.
Java uses JSON.
APIs use JSON.
Web apps use JSON.
Everybody uses JSON.
JSON — це text format for storing and exchanging data.
Він виглядає так:
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
Looks familiar?
Він дуже similar to a Python dictionary.
Python dictionary:
contact = {
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
JSON:
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
Very similar.
Not exactly the same.
Але close enough to feel friendly.
Like cousins.
One speaks Python.
One speaks web.
Чому JSON useful
JSON useful, бо може store structured data.
For example, one contact:
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
A list of contacts:
[
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
},
{
"name": "Marco",
"email": "marco@example.com",
"phone": "987654"
}
]
Це much better than plain text like:
Anna,anna@example.com,123456
Marco,marco@example.com,987654
Why?
Бо JSON keeps structure.
Він knows that each contact has:
name
email
phone
Він can store lists.
Він can store dictionaries.
Він can store nested data.
Plain text — це як writing everything on a napkin.
JSON — це як small organized form.
Still text.
But with structure.
Very nice.
Importing json module
Python has built-in module for JSON.
It is called:
json
To use it, import it:
import json
You do not need to install anything.
Python already includes it.
Very convenient.
Very civilized.
Very “finally, something works without installing seventeen packages”.
Basic idea:
import json
Then you can use:
json.dump()
json.load()
These two functions are very important.
dump saves data to a file.
load loads data from a file.
Simple.
Almost too simple.
Do not worry.
We will make it confusing later.
That is how programming works.
Saving a dictionary to JSON
Створи file:
save_contact.py
Напиши:
import json
contact = {
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
with open("contact.json", "w") as file:
json.dump(contact, file)
Run:
python save_contact.py
або:
python3 save_contact.py
Python creates a file:
contact.json
Inside it, you may see:
{"name": "Anna", "email": "anna@example.com", "phone": "123456"}
This is valid JSON.
Not very pretty.
But valid.
This line saves the dictionary:
json.dump(contact, file)
Important:
json.dump(data, file)
means:
Save this Python data into this file as JSON.
Very useful.
Very clean.
Very structured.
Pretty JSON with indent
Previous JSON works, but it is all on one line.
Можемо зробити prettier.
Use indent=4.
Example:
import json
contact = {
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
with open("contact.json", "w") as file:
json.dump(contact, file, indent=4)
Now contact.json looks like:
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
Much better.
Much easier to read.
Much less “JSON spaghetti”.
Use indent=4 when you want human-readable JSON.
Computers do not care.
Humans care.
And unfortunately, you are human.
Most days.
Loading a dictionary from JSON
Тепер прочитаємо JSON file back.
Створи file:
load_contact.py
Напиши:
import json
with open("contact.json", "r") as file:
contact = json.load(file)
print(contact)
print(contact["name"])
print(contact["email"])
print(contact["phone"])
Output:
{'name': 'Anna', 'email': 'anna@example.com', 'phone': '123456'}
Anna
anna@example.com
123456
This line loads JSON from the file:
contact = json.load(file)
After loading, contact is a Python dictionary again.
That is the magic.
Not fake magic.
Useful magic.
Workflow:
Python dictionary
save as JSON
load from JSON
Python dictionary again
Very important.
Very practical.
Very real-world.
json.dump() vs json.load()
These two names are important.
json.dump(data, file)
saves data to a file.
json.load(file)
loads data from a file.
Remember:
dump = save
load = read
Example:
json.dump(contact, file)
means:
Save contact into file.
Example:
contact = json.load(file)
means:
Read JSON from file and convert it into Python data.
This pair is used constantly.
If you remember only one thing from this lesson, remember:
json.dump() saves.
json.load() loads.
That is the heart of JSON file handling.
Very small heart.
Very useful heart.
Saving a list to JSON
JSON can store lists too.
Створи:
save_tasks_json.py
Напиши:
import json
tasks = [
"Buy milk",
"Study Python",
"Drink coffee"
]
with open("tasks.json", "w") as file:
json.dump(tasks, file, indent=4)
File tasks.json will contain:
[
"Buy milk",
"Study Python",
"Drink coffee"
]
This is a JSON array.
In Python, we call it a list.
In JSON, it is called an array.
Same idea.
Different vocabulary.
Programming loves giving the same thing different names.
Keeps us humble.
And slightly annoyed.
Loading a list from JSON
Створи:
load_tasks_json.py
Напиши:
import json
with open("tasks.json", "r") as file:
tasks = json.load(file)
for task in tasks:
print(f"- {task}")
Output:
- Buy milk
- Study Python
- Drink coffee
JSON array became a Python list.
Very useful.
This is better than reading lines manually.
With plain text, we did:
for line in file:
tasks.append(line.strip())
With JSON, Python can load the whole structure automatically:
tasks = json.load(file)
Cleaner.
More powerful.
Less manual string surgery.
Excellent.
Saving a list of dictionaries
This is where JSON becomes very useful.
Створи:
save_contacts_json.py
Напиши:
import json
contacts = [
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
},
{
"name": "Marco",
"email": "marco@example.com",
"phone": "987654"
}
]
with open("contacts.json", "w") as file:
json.dump(contacts, file, indent=4)
File contacts.json will contain:
[
{
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
},
{
"name": "Marco",
"email": "marco@example.com",
"phone": "987654"
}
]
This is much better than:
Anna,anna@example.com,123456
Marco,marco@example.com,987654
Because structure is clear.
Each contact is an object.
Each object has keys.
The list contains contacts.
Beautiful.
Organized.
Like a filing cabinet.
But less dusty.
Loading a list of dictionaries
Створи:
load_contacts_json.py
Напиши:
import json
with open("contacts.json", "r") as file:
contacts = json.load(file)
for contact in contacts:
print("-----")
print(f"Name: {contact['name']}")
print(f"Email: {contact['email']}")
print(f"Phone: {contact['phone']}")
Output:
-----
Name: Anna
Email: anna@example.com
Phone: 123456
-----
Name: Marco
Email: marco@example.com
Phone: 987654
Now you can save and load structured contact data.
This is real.
This pattern appears everywhere.
A list of dictionaries is one of the most common beginner data structures.
JSON saves it beautifully.
Python loads it easily.
Very nice.
Very practical.
Very backend-friendly.
Python and JSON types
Python data becomes JSON data.
Basic conversion:
Python dict -> JSON object
Python list -> JSON array
Python string -> JSON string
Python int/float -> JSON number
Python True -> JSON true
Python False -> JSON false
Python None -> JSON null
Example Python:
data = {
"name": "Anna",
"age": 25,
"active": True,
"skills": ["Python", "HTML", "CSS"],
"address": None
}
JSON:
{
"name": "Anna",
"age": 25,
"active": true,
"skills": [
"Python",
"HTML",
"CSS"
],
"address": null
}
Notice:
True becomes true
False becomes false
None becomes null
Small differences.
Important differences.
JSON is not exactly Python.
It just looks like Python after drinking tea with JavaScript.
Important JSON rules
JSON has rules.
Very strict rules.
Strings must use double quotes:
"name"
Not single quotes:
'name'
Correct JSON:
{
"name": "Anna"
}
Invalid JSON:
{
'name': 'Anna'
}
Also, JSON does not allow trailing commas.
Correct:
{
"name": "Anna",
"age": 25
}
Wrong:
{
"name": "Anna",
"age": 25,
}
Python dictionaries allow more flexibility.
JSON is stricter.
Very strict.
Like a teacher with a ruler.
But for data.
Handling missing JSON files
If you try to load JSON file that does not exist, Python gives:
FileNotFoundError
Example:
import json
with open("missing.json", "r") as file:
data = json.load(file)
Safer version:
import json
try:
with open("contacts.json", "r") as file:
contacts = json.load(file)
except FileNotFoundError:
contacts = []
print(contacts)
If file exists, contacts are loaded.
If it does not exist, contacts becomes an empty list.
This is useful for first run.
New program.
No data yet.
No disaster.
Just an empty list waiting for life.
Very poetic.
For a file.
Saving after changes
When working with JSON, usual pattern is:
load data
change data
save data
Example:
import json
try:
with open("contacts.json", "r") as file:
contacts = json.load(file)
except FileNotFoundError:
contacts = []
new_contact = {
"name": "Sofia",
"email": "sofia@example.com",
"phone": "555000"
}
contacts.append(new_contact)
with open("contacts.json", "w") as file:
json.dump(contacts, file, indent=4)
This does:
Load contacts.
If file missing, start with empty list.
Add new contact.
Save updated list.
This pattern is extremely important.
You will use it again and again.
Load.
Modify.
Save.
The holy triangle of small data programs.
Very useful.
Very practical.
Very easy to forget one side and wonder why nothing saved.
Міні-програма: save profile as JSON
Створи:
profile_json.py
Напиши:
import json
profile = {
"name": input("Name: "),
"city": input("City: "),
"job": input("Job: ")
}
with open("profile.json", "w") as file:
json.dump(profile, file, indent=4)
print("Profile saved.")
Example input:
Name: Anna
City: Rome
Job: Developer
File profile.json:
{
"name": "Anna",
"city": "Rome",
"job": "Developer"
}
This is simple.
But powerful.
You saved a dictionary as structured data.
You can read it later.
You can edit it.
You can use it in another program.
Small project.
Real idea.
Міні-програма: load profile from JSON
Створи:
show_profile_json.py
Напиши:
import json
try:
with open("profile.json", "r") as file:
profile = json.load(file)
print("----- Profile -----")
print(f"Name: {profile['name']}")
print(f"City: {profile['city']}")
print(f"Job: {profile['job']}")
except FileNotFoundError:
print("No profile found.")
Output:
----- Profile -----
Name: Anna
City: Rome
Job: Developer
Now your program can load structured data.
This is a big step.
Plain text profile would require manual parsing.
JSON makes it direct.
No splitting.
No commas.
No string surgery.
Just load and use.
Beautiful.
Міні-програма: JSON Task Manager
Створи:
json_task_manager.py
Напиши:
import json
FILE_NAME = "tasks.json"
def load_tasks():
try:
with open(FILE_NAME, "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def save_tasks(tasks):
with open(FILE_NAME, "w") as file:
json.dump(tasks, file, indent=4)
def show_menu():
print("----- JSON Task Manager -----")
print("1. Add task")
print("2. Show tasks")
print("3. Remove task")
print("q. Quit")
def add_task(tasks):
task = {
"title": input("Task title: "),
"done": False
}
tasks.append(task)
save_tasks(tasks)
print("Task saved.")
def show_tasks(tasks):
if len(tasks) == 0:
print("No tasks yet.")
else:
print("Tasks:")
for index, task in enumerate(tasks, start=1):
status = "done" if task["done"] else "not done"
print(f"{index}. {task['title']} - {status}")
def remove_task(tasks):
if len(tasks) == 0:
print("No tasks to remove.")
return
show_tasks(tasks)
try:
task_number = int(input("Task number to remove: "))
index = task_number - 1
if index < 0 or index >= len(tasks):
print("Invalid task number.")
return
removed_task = tasks.pop(index)
save_tasks(tasks)
print(f"Removed: {removed_task['title']}")
except ValueError:
print("Please enter a valid number.")
tasks = load_tasks()
while True:
show_menu()
choice = input("Choose an option: ").lower()
if choice == "1":
add_task(tasks)
elif choice == "2":
show_tasks(tasks)
elif choice == "3":
remove_task(tasks)
elif choice == "q":
print("Goodbye.")
break
else:
print("Unknown option.")
This task manager saves tasks as dictionaries.
Each task has:
title
done
Example JSON:
[
{
"title": "Study Python",
"done": false
},
{
"title": "Drink coffee",
"done": false
}
]
This is better than a plain list of task names.
Because now each task can have more information.
Later you can add:
priority
deadline
category
created_at
JSON grows better than plain text.
Plain text is good for simple data.
JSON is better for structured data.
Міні-програма: JSON Contact Book
Створи:
json_contact_book.py
Напиши:
import json
FILE_NAME = "contacts.json"
def load_contacts():
try:
with open(FILE_NAME, "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def save_contacts(contacts):
with open(FILE_NAME, "w") as file:
json.dump(contacts, file, indent=4)
def show_menu():
print("----- JSON Contact Book -----")
print("1. Add contact")
print("2. Show contacts")
print("q. Quit")
def add_contact(contacts):
contact = {
"name": input("Name: "),
"email": input("Email: "),
"phone": input("Phone: ")
}
contacts.append(contact)
save_contacts(contacts)
print("Contact saved.")
def show_contacts(contacts):
if len(contacts) == 0:
print("No contacts yet.")
else:
print("Contacts:")
for contact in contacts:
print("-----")
print(f"Name: {contact['name']}")
print(f"Email: {contact['email']}")
print(f"Phone: {contact['phone']}")
contacts = load_contacts()
while True:
show_menu()
choice = input("Choose an option: ").lower()
if choice == "1":
add_contact(contacts)
elif choice == "2":
show_contacts(contacts)
elif choice == "q":
print("Goodbye.")
break
else:
print("Unknown option.")
This is a real beginner app.
It uses:
- dictionaries;
- lists;
- files;
- JSON;
- functions;
- loops;
- conditions;
- error handling.
Very strong.
Very useful.
Very real.
Your contact data is now structured and saved properly.
This is much better than comma-separated text.
Because if later you add:
address
birthday
notes
company
JSON can handle it nicely.
Plain text starts sweating.
Типова помилка: forgetting import json
Wrong:
with open("data.json", "w") as file:
json.dump(data, file)
If you did not write:
import json
Python gives:
NameError
Correct:
import json
with open("data.json", "w") as file:
json.dump(data, file)
Always import the module before using it.
Python is powerful.
But it does not automatically guess your imports.
It is not a mind reader.
Thankfully.
Типова помилка: using dump and load backwards
Wrong:
data = json.dump(file)
Wrong:
json.load(data, file)
Correct:
json.dump(data, file)
Correct:
data = json.load(file)
Remember:
dump takes data and file
load takes file and returns data
Simple memory trick:
dump data into a file
load data from a file
If this feels confusing, that is normal.
The names are short.
The confusion is long.
Practice helps.
Типова помилка: trying to save unsupported data
JSON can save common data types:
dict
list
str
int
float
bool
None
But not everything.
For example, this may fail:
data = {
"numbers": {1, 2, 3}
}
Why?
Because {1, 2, 3} is a set.
JSON does not support Python sets directly.
If you need to save a set, convert it to a list:
data = {
"numbers": list({1, 2, 3})
}
For beginners, use:
dictionaries
lists
strings
numbers
booleans
None
These work well with JSON.
Keep it simple.
Simple survives.
Complicated asks for coffee.
Типова помилка: invalid JSON file
If JSON file is broken, json.load() can fail.
Example invalid JSON:
{
"name": "Anna",
}
The trailing comma makes it invalid.
Python may raise:
json.JSONDecodeError
Safer loading:
import json
try:
with open("data.json", "r") as file:
data = json.load(file)
except FileNotFoundError:
data = []
except json.JSONDecodeError:
print("JSON file is broken.")
data = []
This handles:
missing file
broken JSON file
Very useful.
Especially when humans edit JSON manually.
Humans and commas are a dangerous combination.
Very dangerous.
Типова помилка: forgetting to save after append
Wrong:
contacts = load_contacts()
contact = {
"name": "Anna",
"email": "anna@example.com",
"phone": "123456"
}
contacts.append(contact)
print("Contact added.")
This adds contact only in memory.
But it does not save to file.
When program ends, new contact disappears.
Correct:
contacts.append(contact)
save_contacts(contacts)
Remember the pattern:
load
modify
save
If you modify data but do not save it, file does not change.
Python is not going to save it emotionally.
You must tell it.
Clearly.
With code.
Типова помилка: opening JSON with append mode
This is usually wrong:
with open("contacts.json", "a") as file:
json.dump(contact, file)
Appending JSON objects directly can create invalid JSON.
Example broken file:
{"name": "Anna"}{"name": "Marco"}
That is not a valid JSON list.
For JSON files, usually do this:
load existing list
append item to list
save whole list again
Example:
contacts = load_contacts()
contacts.append(new_contact)
save_contacts(contacts)
This keeps JSON file valid.
Append mode useful for plain text logs.
For JSON structured data, be careful.
Very careful.
JSON likes structure.
Not random objects glued together.
Практика
Створи:
practice_json.py
Напиши program, яка:
- asks the user for a book title;
- asks the user for an author;
- asks the user for a year;
- saves the book as JSON in
book.json; - loads the book back;
- prints the book nicely.
Example solution:
import json
book = {
"title": input("Title: "),
"author": input("Author: "),
"year": input("Year: ")
}
with open("book.json", "w") as file:
json.dump(book, file, indent=4)
with open("book.json", "r") as file:
loaded_book = json.load(file)
print("----- Book -----")
print(f"Title: {loaded_book['title']}")
print(f"Author: {loaded_book['author']}")
print(f"Year: {loaded_book['year']}")
This practice teaches:
- creating a dictionary;
- saving dictionary as JSON;
- loading JSON;
- using loaded dictionary.
Simple.
Useful.
Very structured.
Very good.
Міні-завдання
Створи:
library_json.py
Build a small library program that:
- saves books to
books.json; - loads books on start;
- lets the user add a book;
- lets the user show all books;
- each book has title, author, and year;
- handles missing file safely.
Example structure:
import json
FILE_NAME = "books.json"
def load_books():
try:
with open(FILE_NAME, "r") as file:
return json.load(file)
except FileNotFoundError:
return []
def save_books(books):
with open(FILE_NAME, "w") as file:
json.dump(books, file, indent=4)
def add_book(books):
book = {
"title": input("Title: "),
"author": input("Author: "),
"year": input("Year: ")
}
books.append(book)
save_books(books)
print("Book saved.")
def show_books(books):
if len(books) == 0:
print("No books yet.")
else:
print("Books:")
for book in books:
print("-----")
print(f"Title: {book['title']}")
print(f"Author: {book['author']}")
print(f"Year: {book['year']}")
def show_menu():
print("----- Library -----")
print("1. Add book")
print("2. Show books")
print("q. Quit")
books = load_books()
while True:
show_menu()
choice = input("Choose an option: ").lower()
if choice == "1":
add_book(books)
elif choice == "2":
show_books(books)
elif choice == "q":
print("Goodbye.")
break
else:
print("Unknown option.")
This is a real small application.
It uses JSON to store a list of dictionaries.
That is a very important pattern.
Very useful for future projects.
You can adapt this structure for:
contacts
tasks
products
students
courses
expenses
workouts
The idea is the same.
Load data.
Modify data.
Save data.
Congratulations.
You are building reusable patterns.
That is how developers grow.
Slowly.
Painfully.
With snacks.
Extra challenge: improve the task manager
Take JSON task manager and add a new option:
4. Mark task as done
Each task already has:
"done": False
Your job:
- show tasks with numbers;
- ask which task to mark as done;
- change
"done"toTrue; - save the tasks again.
Hint:
tasks[index]["done"] = True
save_tasks(tasks)
This is a very good challenge.
It teaches updating structured data.
Not just adding.
Not just deleting.
Updating.
That is what real apps do all the time.
Create.
Read.
Update.
Delete.
Later you will hear this called CRUD.
Very serious word.
Very simple idea.
Very useful.
Checklist для початківців
When JSON code does not work, check:
Did I import json?
Am I using json.dump(data, file)?
Am I using data = json.load(file)?
Did I open the file in the correct mode?
Did I use indent=4 for readable JSON?
Does the file exist before reading?
Should I handle FileNotFoundError?
Is the JSON file valid?
Did I accidentally leave a trailing comma?
Am I trying to save an unsupported Python type?
Did I save after changing the data?
Am I appending to JSON incorrectly?
JSON bugs are usually about:
file missing
invalid JSON
wrong dump/load usage
forgotten save
wrong data structure
Fix calmly.
Read the error message.
Check the file.
Check the data.
Drink coffee if needed.
But do not throw the laptop.
The laptop is innocent.
Usually.
Підсумок
Сьогодні ти вивчив:
- JSON is a common format for structured data;
- JSON looks similar to Python dictionaries and lists;
- Python uses built-in
jsonmodule; json.dump()saves Python data to JSON file;json.load()loads JSON data from a file;indent=4makes JSON readable;- dictionaries can be saved as JSON objects;
- lists can be saved as JSON arrays;
- lists of dictionaries are very useful with JSON;
True,False, andNonebecometrue,false, andnull;- JSON requires double quotes;
- JSON does not allow trailing commas;
- missing JSON files can be handled with
FileNotFoundError; - broken JSON can raise
json.JSONDecodeError; - common pattern is load, modify, save;
- JSON is better than plain text for structured data.
Це великий step.
Твої programs тепер можуть save real structured data.
Not just lines of text.
They can save contacts.
Tasks.
Books.
Profiles.
Products.
Anything that fits into dictionaries and lists.
This is the kind of data structure used in real applications.
Small beginner programs are now becoming serious.
Still small.
But serious.
Like a tiny engineer with a clipboard.
Наступна лекція
У наступній лекції ми вивчимо virtual environments і installing packages.
So far, we used only Python’s built-in tools.
But real Python projects often use external packages.
Ти навчишся create a virtual environment:
python -m venv .venv
Activate it.
Install packages with pip.
And keep project dependencies organized.
Це дуже important before building bigger projects.
Бо installing packages globally is how chaos begins.
And we already have enough chaos.
Very Python.
Very real-world.
Very necessary.