← Back to course

JSON: zapisywanie danych strukturalnych

JSON: zapisywanie danych strukturalnych

Witaj z powrotem.

W poprzedniej lekcji nauczyłeś się modułów i importów.

Twoje programy nauczyły się dzielić kod na wiele plików.

Pisałeś projekty takie jak:

main.py
tasks.py
safe_input.py

Bardzo dobrze.

Twój kod jest teraz bardziej uporządkowany.

Mniej gigantycznego pliku.

Mniej lasagne z kodu.

Mniej “gdzie ja włożyłem tę funkcję?”

Świetny postęp.

Ale teraz mamy kolejny problem.

W poprzednich lekcjach zapisywaliśmy dane w zwykłych plikach tekstowych.

Na przykład:

Anna,anna@example.com,123456
Marco,marco@example.com,987654

To działa.

Ale nie jest idealne.

Co jeśli dane staną się bardziej złożone?

Co jeśli jeden kontakt ma więcej pól?

Co jeśli chcesz zapisać listę słowników?

Co jeśli użytkownik wpisze przecinek w imieniu?

Chaos.

Pliki tekstowe są użyteczne.

Ale do danych strukturalnych JSON jest lepszy.

JSON pozwala zapisywać dane takie jak:

contact = {
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
}

do pliku.

A potem załadować je później z powrotem.

To bardzo ważne.

JSON jest używany wszędzie.

API.

Aplikacje webowe.

Pliki konfiguracyjne.

Bazy danych.

Komunikacja między frontendem i backendem.

Małe skrypty, które przypadkiem stają się prawdziwym software.

Bardzo użyteczne.

Bardzo praktyczne.

Bardzo przyjazne dla Pythona.

Czego się nauczysz

W tej lekcji nauczysz się:

Pod koniec tej lekcji twoje programy będą potrafiły poprawnie zapisywać dane strukturalne.

Nie tylko proste linie.

Prawdziwe dane.

Listy.

Słowniki.

Informacje zagnieżdżone.

Bardzo potężne.

Bardzo użyteczne.

Bardzo “teraz to zaczyna wyglądać jak prawdziwa aplikacja”.

Czym jest JSON?

JSON oznacza:

JavaScript Object Notation

Nie panikuj.

Mimo że w nazwie jest JavaScript, JSON jest używany przez wiele języków.

Python używa JSON.

JavaScript używa JSON.

Java używa JSON.

API używają JSON.

Aplikacje webowe używają JSON.

Wszyscy używają JSON.

JSON to format tekstowy do przechowywania i wymiany danych.

Wygląda tak:

{
  "name": "Anna",
  "email": "anna@example.com",
  "phone": "123456"
}

Wygląda znajomo?

Jest bardzo podobny do słownika Pythona.

Słownik Python:

contact = {
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
}

JSON:

{
  "name": "Anna",
  "email": "anna@example.com",
  "phone": "123456"
}

Bardzo podobne.

Nie dokładnie to samo.

Ale wystarczająco podobne, żeby wyglądało przyjaźnie.

Jak kuzyni.

Jeden mówi Pythonem.

Drugi mówi webem.

Dlaczego JSON jest użyteczny

JSON jest użyteczny, bo potrafi przechowywać dane strukturalne.

Na przykład jeden kontakt:

{
  "name": "Anna",
  "email": "anna@example.com",
  "phone": "123456"
}

Lista kontaktów:

[
  {
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
  },
  {
    "name": "Marco",
    "email": "marco@example.com",
    "phone": "987654"
  }
]

To jest dużo lepsze niż zwykły tekst:

Anna,anna@example.com,123456
Marco,marco@example.com,987654

Dlaczego?

Bo JSON zachowuje strukturę.

Wie, że każdy kontakt ma:

name
email
phone

Może przechowywać listy.

Może przechowywać słowniki.

Może przechowywać dane zagnieżdżone.

Zwykły tekst jest jak zapisanie wszystkiego na serwetce.

JSON jest jak mały uporządkowany formularz.

Nadal tekst.

Ale ze strukturą.

Bardzo ładnie.

Importowanie modułu json

Python ma wbudowany moduł do JSON.

Nazywa się:

json

Żeby go użyć, zaimportuj go:

import json

Nie musisz nic instalować.

Python już go zawiera.

Bardzo wygodnie.

Bardzo cywilizowanie.

Bardzo “w końcu coś działa bez instalowania siedemnastu paczek”.

Podstawowa idea:

import json

Potem możesz używać:

json.dump()
json.load()

Te dwie funkcje są bardzo ważne.

dump zapisuje dane do pliku.

load ładuje dane z pliku.

Proste.

Prawie zbyt proste.

Nie martw się.

Później i tak zrobi się trochę zamieszania.

Tak działa programowanie.

Zapisywanie słownika do JSON

Utwórz plik:

save_contact.py

Napisz:

import json

contact = {
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
}

with open("contact.json", "w") as file:
    json.dump(contact, file)

Uruchom:

python save_contact.py

albo:

python3 save_contact.py

Python utworzy plik:

contact.json

W środku możesz zobaczyć:

{"name": "Anna", "email": "anna@example.com", "phone": "123456"}

To jest poprawny JSON.

Niezbyt piękny.

Ale poprawny.

Ta linia zapisuje słownik:

json.dump(contact, file)

Ważne:

json.dump(data, file)

oznacza:

Zapisz te dane Pythona do tego pliku jako JSON.

Bardzo użyteczne.

Bardzo czyste.

Bardzo strukturalne.

Ładny JSON z indent

Poprzedni JSON działa, ale jest cały w jednej linii.

Możemy zrobić go ładniejszym.

Użyj indent=4.

Przykład:

import json

contact = {
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
}

with open("contact.json", "w") as file:
    json.dump(contact, file, indent=4)

Teraz contact.json wygląda tak:

{
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
}

Dużo lepiej.

Dużo łatwiej czytać.

Dużo mniej “spaghetti JSON”.

Używaj indent=4, kiedy chcesz JSON czytelny dla ludzi.

Komputerom to obojętne.

Ludziom nie.

A niestety jesteś człowiekiem.

Przez większość dni.

Ładowanie słownika z JSON

Teraz odczytajmy plik JSON z powrotem.

Utwórz plik:

load_contact.py

Napisz:

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

Ta linia ładuje JSON z pliku:

contact = json.load(file)

Po załadowaniu contact znowu jest słownikiem Pythona.

To jest magia.

Nie fałszywa magia.

Użyteczna magia.

Workflow:

Słownik Python
zapis jako JSON
ładowanie z JSON
znowu słownik Python

Bardzo ważne.

Bardzo praktyczne.

Bardzo real-world.

json.dump() vs json.load()

Te dwie nazwy są ważne.

json.dump(data, file)

zapisuje dane do pliku.

json.load(file)

ładuje dane z pliku.

Pamiętaj:

dump = zapisz
load = odczytaj

Przykład:

json.dump(contact, file)

oznacza:

Zapisz contact do pliku.

Przykład:

contact = json.load(file)

oznacza:

Odczytaj JSON z pliku i zamień go na dane Pythona.

Ta para jest używana ciągle.

Jeśli zapamiętasz tylko jedną rzecz z tej lekcji, zapamiętaj:

json.dump() zapisuje.
json.load() ładuje.

To serce obsługi plików JSON.

Małe serce.

Bardzo użyteczne serce.

Zapisywanie listy do JSON

JSON może zapisywać też listy.

Utwórz:

save_tasks_json.py

Napisz:

import json

tasks = [
    "Buy milk",
    "Study Python",
    "Drink coffee"
]

with open("tasks.json", "w") as file:
    json.dump(tasks, file, indent=4)

Plik tasks.json będzie zawierał:

[
    "Buy milk",
    "Study Python",
    "Drink coffee"
]

To jest tablica JSON.

W Pythonie nazywamy to listą.

W JSON nazywa się to array.

Ta sama idea.

Inne słownictwo.

Programowanie kocha dawać tej samej rzeczy różne nazwy.

Trzyma nas to w pokorze.

I lekko denerwuje.

Ładowanie listy z JSON

Utwórz:

load_tasks_json.py

Napisz:

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

Tablica JSON stała się listą Pythona.

Bardzo użyteczne.

To jest lepsze niż ręczne czytanie linii.

Przy zwykłym tekście robiliśmy:

for line in file:
    tasks.append(line.strip())

Z JSON Python może automatycznie załadować całą strukturę:

tasks = json.load(file)

Czyściej.

Mocniej.

Mniej ręcznej chirurgii na stringach.

Świetnie.

Zapisywanie listy słowników

Tutaj JSON robi się naprawdę użyteczny.

Utwórz:

save_contacts_json.py

Napisz:

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)

Plik contacts.json będzie zawierał:

[
    {
        "name": "Anna",
        "email": "anna@example.com",
        "phone": "123456"
    },
    {
        "name": "Marco",
        "email": "marco@example.com",
        "phone": "987654"
    }
]

To jest dużo lepsze niż:

Anna,anna@example.com,123456
Marco,marco@example.com,987654

Bo struktura jest jasna.

Każdy kontakt jest obiektem.

Każdy obiekt ma klucze.

Lista zawiera kontakty.

Pięknie.

Uporządkowanie.

Jak szafka na dokumenty.

Tylko mniej zakurzona.

Ładowanie listy słowników

Utwórz:

load_contacts_json.py

Napisz:

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

Teraz możesz zapisywać i ładować strukturalne dane kontaktów.

To jest realne.

Ten pattern pojawia się wszędzie.

Lista słowników to jedna z najczęstszych struktur danych dla początkujących.

JSON zapisuje ją pięknie.

Python ładuje ją łatwo.

Bardzo dobrze.

Bardzo praktycznie.

Bardzo backend-friendly.

Typy Python i JSON

Dane Pythona stają się danymi JSON.

Podstawowa konwersja:

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

Przykład 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
}

Zauważ:

True staje się true
False staje się false
None staje się null

Małe różnice.

Ważne różnice.

JSON nie jest dokładnie Pythonem.

Po prostu wygląda jak Python po herbacie z JavaScriptem.

Ważne zasady JSON

JSON ma zasady.

Bardzo surowe zasady.

Stringi muszą używać podwójnych cudzysłowów:

"name"

Nie pojedynczych:

'name'

Poprawny JSON:

{
    "name": "Anna"
}

Niepoprawny JSON:

{
    'name': 'Anna'
}

JSON nie pozwala też na przecinki na końcu.

Poprawnie:

{
    "name": "Anna",
    "age": 25
}

Źle:

{
    "name": "Anna",
    "age": 25,
}

Słowniki Pythona pozwalają na więcej elastyczności.

JSON jest bardziej surowy.

Bardzo surowy.

Jak nauczyciel z linijką.

Ale dla danych.

Obsługa brakujących plików JSON

Jeśli spróbujesz załadować plik JSON, który nie istnieje, Python da:

FileNotFoundError

Przykład:

import json

with open("missing.json", "r") as file:
    data = json.load(file)

Bezpieczniejsza wersja:

import json

try:
    with open("contacts.json", "r") as file:
        contacts = json.load(file)
except FileNotFoundError:
    contacts = []

print(contacts)

Jeśli plik istnieje, kontakty zostaną załadowane.

Jeśli nie istnieje, contacts stanie się pustą listą.

To jest użyteczne przy pierwszym uruchomieniu.

Nowy program.

Jeszcze brak danych.

Brak katastrofy.

Tylko pusta lista czekająca na życie.

Bardzo poetycko.

Jak na plik.

Zapisywanie po zmianach

Podczas pracy z JSON normalny pattern to:

załaduj dane
zmień dane
zapisz dane

Przykład:

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)

To robi:

Ładuje kontakty.
Jeśli pliku nie ma, startuje z pustą listą.
Dodaje nowy kontakt.
Zapisuje zaktualizowaną listę.

Ten pattern jest ekstremalnie ważny.

Będziesz go używać wiele razy.

Załaduj.

Zmień.

Zapisz.

Święty trójkąt małych programów z danymi.

Bardzo użyteczne.

Bardzo praktyczne.

Bardzo łatwo zapomnieć jeden bok i zastanawiać się, czemu nic się nie zapisało.

Mini program: zapis profilu jako JSON

Utwórz:

profile_json.py

Napisz:

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.")

Przykładowy input:

Name: Anna
City: Rome
Job: Developer

Plik profile.json:

{
    "name": "Anna",
    "city": "Rome",
    "job": "Developer"
}

To proste.

Ale mocne.

Zapisałeś słownik jako dane strukturalne.

Możesz odczytać go później.

Możesz go edytować.

Możesz użyć go w innym programie.

Mały projekt.

Realna idea.

Mini program: ładowanie profilu z JSON

Utwórz:

show_profile_json.py

Napisz:

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

Teraz twój program może ładować dane strukturalne.

To duży krok.

Profil w zwykłym tekście wymagałby ręcznego parsowania.

JSON robi to bezpośrednio.

Bez split.

Bez przecinków.

Bez chirurgii na stringach.

Po prostu załaduj i użyj.

Pięknie.

Mini program: task manager JSON

Utwórz:

json_task_manager.py

Napisz:

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.")

Ten task manager zapisuje zadania jako słowniki.

Każde zadanie ma:

title
done

Przykład JSON:

[
    {
        "title": "Study Python",
        "done": false
    },
    {
        "title": "Drink coffee",
        "done": false
    }
]

To lepsze niż zwykła lista nazw zadań.

Bo teraz każde zadanie może mieć więcej informacji.

Później możesz dodać:

priority
deadline
category
created_at

JSON rośnie lepiej niż zwykły tekst.

Zwykły tekst jest dobry do prostych danych.

JSON jest lepszy do danych strukturalnych.

Mini program: książka kontaktów JSON

Utwórz:

json_contact_book.py

Napisz:

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.")

To prawdziwa aplikacja dla początkujących.

Używa:

Bardzo mocne.

Bardzo użyteczne.

Bardzo realne.

Twoje dane kontaktów są teraz strukturalne i poprawnie zapisane.

To dużo lepsze niż tekst rozdzielony przecinkami.

Bo jeśli później dodasz:

address
birthday
notes
company

JSON poradzi sobie ładnie.

Zwykły tekst zaczyna się pocić.

Typowy błąd: zapomnienie import json

Źle:

with open("data.json", "w") as file:
    json.dump(data, file)

Jeśli nie napisałeś:

import json

Python da:

NameError

Poprawnie:

import json

with open("data.json", "w") as file:
    json.dump(data, file)

Zawsze importuj moduł przed użyciem.

Python jest potężny.

Ale nie zgaduje automatycznie twoich importów.

Nie czyta w myślach.

Na szczęście.

Typowy błąd: używanie dump i load odwrotnie

Źle:

data = json.dump(file)

Źle:

json.load(data, file)

Poprawnie:

json.dump(data, file)

Poprawnie:

data = json.load(file)

Pamiętaj:

dump bierze dane i plik
load bierze plik i zwraca dane

Mała sztuczka pamięciowa:

dump data into a file
load data from a file

Jeśli to wydaje się mylące, to normalne.

Nazwy są krótkie.

Zamieszanie jest długie.

Praktyka pomaga.

Typowy błąd: próba zapisania nieobsługiwanych danych

JSON może zapisywać popularne typy:

dict
list
str
int
float
bool
None

Ale nie wszystko.

Na przykład to może się nie udać:

data = {
    "numbers": {1, 2, 3}
}

Dlaczego?

Bo {1, 2, 3} to set.

JSON nie obsługuje bezpośrednio pythonowych setów.

Jeśli musisz zapisać set, zamień go na listę:

data = {
    "numbers": list({1, 2, 3})
}

Dla początkujących używaj:

słowników
list
stringów
liczb
booleanów
None

Te typy dobrze działają z JSON.

Trzymaj prosto.

Proste przeżywa.

Skomplikowane prosi o kawę.

Typowy błąd: niepoprawny plik JSON

Jeśli plik JSON jest zepsuty, json.load() może się nie udać.

Przykład niepoprawnego JSON:

{
    "name": "Anna",
}

Przecinek na końcu sprawia, że JSON jest niepoprawny.

Python może zgłosić:

json.JSONDecodeError

Bezpieczniejsze ładowanie:

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 = []

To obsługuje:

brakujący plik
zepsuty plik JSON

Bardzo użyteczne.

Szczególnie kiedy ludzie ręcznie edytują JSON.

Ludzie i przecinki to niebezpieczna kombinacja.

Bardzo niebezpieczna.

Typowy błąd: zapomnienie zapisu po append

Źle:

contacts = load_contacts()

contact = {
    "name": "Anna",
    "email": "anna@example.com",
    "phone": "123456"
}

contacts.append(contact)

print("Contact added.")

To dodaje kontakt tylko w pamięci.

Ale nie zapisuje go do pliku.

Kiedy program się kończy, nowy kontakt znika.

Poprawnie:

contacts.append(contact)
save_contacts(contacts)

Pamiętaj pattern:

load
modify
save

Jeśli zmieniasz dane, ale ich nie zapisujesz, plik się nie zmienia.

Python nie zapisze tego emocjonalnie.

Musisz mu powiedzieć.

Jasno.

Kodом.

Typowy błąd: otwieranie JSON w trybie append

To zwykle jest złe:

with open("contacts.json", "a") as file:
    json.dump(contact, file)

Dopisywanie obiektów JSON bezpośrednio może stworzyć niepoprawny JSON.

Przykład zepsutego pliku:

{"name": "Anna"}{"name": "Marco"}

To nie jest poprawna lista JSON.

Dla plików JSON zwykle rób tak:

załaduj istniejącą listę
dodaj element do listy
zapisz całą listę ponownie

Przykład:

contacts = load_contacts()
contacts.append(new_contact)
save_contacts(contacts)

To utrzymuje plik JSON poprawnym.

Tryb append jest użyteczny dla zwykłych logów tekstowych.

Dla danych strukturalnych JSON uważaj.

Bardzo uważaj.

JSON lubi strukturę.

Nie losowe obiekty przyklejone do siebie.

Praktyka

Utwórz:

practice_json.py

Napisz program, który:

Przykładowe rozwiązanie:

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']}")

Ta praktyka uczy:

Prosto.

Użytecznie.

Bardzo strukturalnie.

Bardzo dobrze.

Mini wyzwanie

Utwórz:

library_json.py

Zbuduj mały program biblioteczny, który:

Przykładowa struktura:

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.")

To prawdziwa mała aplikacja.

Używa JSON do przechowywania listy słowników.

To bardzo ważny pattern.

Bardzo użyteczny dla przyszłych projektów.

Możesz dostosować tę strukturę do:

contacts
tasks
products
students
courses
expenses
workouts

Idea jest taka sama.

Załaduj dane.

Zmień dane.

Zapisz dane.

Gratulacje.

Budujesz wielokrotnego użytku patterny.

Tak rosną developerzy.

Powoli.

Boleśnie.

Ze snackami.

Extra challenge: ulepsz task manager

Weź JSON task manager i dodaj nową opcję:

4. Mark task as done

Każde zadanie już ma:

"done": False

Twoje zadanie:

Podpowiedź:

tasks[index]["done"] = True
save_tasks(tasks)

To bardzo dobre wyzwanie.

Uczy aktualizowania danych strukturalnych.

Nie tylko dodawania.

Nie tylko usuwania.

Aktualizowania.

To robią prawdziwe aplikacje cały czas.

Create.

Read.

Update.

Delete.

Później usłyszysz, że to nazywa się CRUD.

Bardzo poważne słowo.

Bardzo prosta idea.

Bardzo użyteczna.

Checklist dla początkujących

Kiedy kod JSON nie działa, sprawdź:

Czy zaimportowałem json?
Czy używam json.dump(data, file)?
Czy używam data = json.load(file)?
Czy otworzyłem plik w poprawnym trybie?
Czy użyłem indent=4 dla czytelnego JSON?
Czy plik istnieje przed czytaniem?
Czy powinienem obsłużyć FileNotFoundError?
Czy plik JSON jest poprawny?
Czy przypadkiem zostawiłem przecinek na końcu?
Czy próbuję zapisać nieobsługiwany typ Pythona?
Czy zapisałem po zmianie danych?
Czy źle dopisuję do JSON?

Błędy JSON zwykle dotyczą:

brakującego pliku
niepoprawnego JSON
złego użycia dump/load
zapomnianego save
złej struktury danych

Napraw spokojnie.

Przeczytaj komunikat błędu.

Sprawdź plik.

Sprawdź dane.

Wypij kawę, jeśli trzeba.

Ale nie rzucaj laptopem.

Laptop jest niewinny.

Zwykle.

Podsumowanie

Dzisiaj nauczyłeś się:

To duży krok.

Twoje programy mogą teraz zapisywać prawdziwe dane strukturalne.

Nie tylko linie tekstu.

Mogą zapisywać kontakty.

Zadania.

Książki.

Profile.

Produkty.

Wszystko, co mieści się w słownikach i listach.

To taki typ struktury danych, którego używa się w prawdziwych aplikacjach.

Małe programy dla początkujących stają się teraz poważne.

Nadal małe.

Ale poważne.

Jak malutki inżynier z clipboardem.

Następna lekcja

W następnej lekcji nauczymy się virtual environments i instalowania paczek.

Do tej pory używaliśmy tylko wbudowanych narzędzi Pythona.

Ale prawdziwe projekty Python często używają zewnętrznych paczek.

Nauczysz się tworzyć virtual environment:

python -m venv .venv

Aktywować go.

Instalować paczki przez pip.

I utrzymywać zależności projektu w porządku.

To bardzo ważne przed budowaniem większych projektów.

Bo instalowanie paczek globalnie to sposób, w jaki zaczyna się chaos.

A chaosu mamy już wystarczająco.

Bardzo Python.

Bardzo real-world.

Bardzo konieczne.