# Opslaan en serialiseren met de Python standaardbibliotheek: `json`, `pickle`, `csv` Wanneer je data in een bestand wilt bewaren of over het netwerk wilt verzenden, heb je **serialisatie** nodig. Python biedt hiervoor drie vrij verschillende standaardtools: **`json`**, **`pickle`** en **`csv`**. ![Data delivery formats](/media/editor_temp/6/82b2d285-16b0-473a-b88a-cd9a6f6582f2.png) * **`json`**: leesbaar tekstformaat, sterk in inter‑taaluitwisseling * **`pickle`**: binaire vorm die Python‑objecten exact bewaart, krachtig maar met risico’s * **`csv`**: eenvoudig tekstformaat voor tabulaire data, zeer universeel In dit artikel leggen we uit hoe je de juiste module kiest op basis van *wat* je wilt doen. --- ## 1. JSON {#sec-c0452ee3f8b9} ### 1.1 Overzicht {#sec-573894aef250} JSON (JavaScript Object Notation) is **tekstgebaseerd** en **taal‑onafhankelijk**. Het wordt veel gebruikt voor configuratiebestanden, API‑responses, logs en alles wat je met andere systemen wilt delen. In Python wordt het rechtstreeks beheerd met de `json` module. ### 1.2 Kern‑API (alleen de meest gebruikte) {#sec-7388e1478aff} * `json.dump(obj, fp, ...)` / `json.load(fp, ...)` : opslaan/laden naar een bestand * `json.dumps(obj, ...)` / `json.loads(s, ...)` : omzetten naar/van een string Belangrijke opties: * `ensure_ascii=False` : internationale tekens (bijv. CJK) niet escapen, maar direct schrijven * `indent=2` : leesbare, mooi geformatteerde output * `default=...` : een “omweg” voor types die JSON niet kent ### 1.3 Voorbeeld (basis) {#sec-57d0c0653337} ```python import json data = { "name": "Alice", "age": 30, "skills": ["Python", "Data Science"] } with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) with open("data.json", "r", encoding="utf-8") as f: loaded = json.load(f) print(loaded) ``` ### 1.4 JSON‑type‑beperkingen eenvoudig oplossen {#sec-a43d0fe8a199} JSON ondersteunt standaard alleen `dict`, `list`, `str`, `int/float`, `bool` en `None`. Complexere types, zoals `datetime`, moeten via `default` omgezet worden. ```python import json from datetime import datetime, timezone payload = {"created_at": datetime.now(timezone.utc)} def to_jsonable(obj): if isinstance(obj, datetime): return obj.isoformat() raise TypeError(f"Not JSON serializable: {type(obj)!r}") s = json.dumps(payload, default=to_jsonable, ensure_ascii=False) print(s) ``` ### 1.5 Voor- en nadelen {#sec-667d6fad184b} **Voordelen** * Taaldonker, ideaal voor uitwisseling * Tekst, dus makkelijk debuggen en versiebeheer * Geen code‑uitvoering bij laden, dus veiliger dan `pickle` **Nadelen** * Beperkte type‑expressie (bijv. `datetime`, `set`, `Decimal`, binaire data) * Bij grote datasets kan het minder efficiënt zijn qua grootte en snelheid --- ## 2. Pickle {#sec-7417b1955ccc} ### 2.1 Overzicht {#sec-1889607ea8cb} `pickle` serialiseert Python‑objecten *exact* zoals ze zijn. Het resultaat is een binaire byte‑reeks; bij laden krijg je vrijwel dezelfde objecten terug. Pickle is vooral handig wanneer: * Je complexe Python‑objecten wilt bewaren (bijv. eigen klassen, geneste structuren, getrainde modellen) * Er geen behoefte is om met andere talen te communiceren **Wees voorzichtig** bij het laden van pickle‑bestanden uit onbekende bronnen, want `pickle.load()` kan willekeurige code uitvoeren. ### 2.2 Kern‑API (de vier meest gebruikte) {#sec-a0a97fe87a25} * `pickle.dump(obj, file, protocol=...)` : object → bestand (binair) * `pickle.load(file)` : bestand → object * `pickle.dumps(obj, protocol=...)` : object → bytes * `pickle.loads(data)` : bytes → object ```python import pickle data = {"a": [1, 2, 3], "b": ("x", "y")} with open("data.pkl", "wb") as f: pickle.dump(data, f) with open("data.pkl", "rb") as f: loaded = pickle.load(f) print(loaded) ``` ### 2.3 Protocol – waarom het belangrijk is {#sec-1f8e5565848c} Het *protocol* bepaalt de interne opmaak van de pickle‑data. Zonder expliciete keuze gebruikt Python het meest geschikte standaardprotocol. * **Oudere Python‑versies**: soms moet je een lager protocol gebruiken voor compatibiliteit. * **Optimalisatie**: het nieuwste protocol (`pickle.HIGHEST_PROTOCOL`) levert vaak kleinere en snellere bestanden. ```python import pickle with open("data.pkl", "wb") as f: pickle.dump({"x": 1}, f, protocol=pickle.HIGHEST_PROTOCOL) ``` ### 2.4 Belangrijkste veiligheidswaarschuwing {#sec-007b70a5e9ec} `pickle.load()` voert de *herstel‑logica* uit die in het bestand is opgeslagen. Laden van een pickle uit een onbeveiligde bron kan leiden tot willekeurige code‑uitvoering. * **Veilig**: open nooit een pickle van een onbekende bron. * **Vooruit**: gebruik bij uitwisseling een tekstgebaseerd formaat zoals `json`. ### 2.5 Voor- en nadelen {#sec-bbd5a24bec31} **Voordelen** * Bewaart vrijwel elk Python‑object * Meestal sneller en handiger dan `json` voor complexe data **Nadelen** * Beveiligingsrisico bij onbetrouwbare data * Alleen Python‑compatibel * Versie‑compatibiliteit kan een probleem zijn als klassen veranderen --- ## 3. CSV {#sec-99e590b24e50} ### 3.1 Overzicht {#sec-1265cc44a461} CSV (Comma‑Separated Values) is het eenvoudigste formaat voor tabulaire data. Het wordt vaak gebruikt voor spreadsheets, data‑export/import en eenvoudige log‑dump. ### 3.2 Kern‑API (alleen de meest gebruikte) {#sec-5b2e4c37cce5} * `csv.reader`, `csv.writer` : werken met lijsten * `csv.DictReader`, `csv.DictWriter` : werken met dictionaries (meestal handiger) ### 3.3 Voorbeeld (DictWriter/DictReader) {#sec-524921270351} ```python import csv data = [ {"name": "Alice", "age": 30, "city": "Seoul"}, {"name": "Bob", "age": 25, "city": "Busan"}, ] with open("people.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["name", "age", "city"]) writer.writeheader() writer.writerows(data) with open("people.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) loaded = list(reader) print(loaded) ``` ### 3.4 Drie belangrijke aandachtspunten {#sec-3db1b7ed8444} 1. **`newline=""`** gebruiken – vooral op Windows voorkomt dubbele nieuwe regels. 2. **Alle waarden zijn strings** – bij het lezen moet je zelf de types converteren. 3. **Speciale tekens** (komma, aanhalingstekens, nieuwe regels) kunnen de structuur verstoren; het `csv`‑module is hier veilig voor. ### 3.5 Voor- en nadelen {#sec-6a8ca4891a8e} **Voordelen** * Zeer lichtgewicht en universeel leesbaar * Ideaal voor eenvoudige tabulaire data **Nadelen** * Niet geschikt voor geneste of complexe structuren * Geen type‑informatie, dus extra conversie nodig --- ## 4. Vergelijking & keuze‑gids {#sec-6304ec188cc0} | Kenmerk | JSON | Pickle | CSV | |---------|------|--------|-----| | Taal‑compatibiliteit | Zeer goed | Alleen Python | Zeer goed | | Leesbaarheid | Hoog | Laag (binair) | Hoog | | Type‑expressie | Beperkt | Zeer hoog | Beperkt | | Veiligheid | Relatief veilig | **Let op** | Relatief veilig | | Data‑vorm | Boom (genest) | Exact Python‑object | Tabel (rij/kolom) | **Korte samenvatting** * **Andere systemen delen** → `json` * **Python‑objecten volledig bewaren** → `pickle` (maar alleen van vertrouwde bronnen) * **Rij/kolom export** → `csv` --- ## 5. Hetzelfde data in drie formaten opslaan & laden {#sec-21f8c2a6d6c9} ```python import json, pickle, csv data = [ {"id": 1, "name": "Alice", "score": 95.5}, {"id": 2, "name": "Bob", "score": 88.0}, ] # 1) JSON with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) with open("data.json", "r", encoding="utf-8") as f: json_loaded = json.load(f) # 2) Pickle with open("data.pkl", "wb") as f: pickle.dump(data, f) with open("data.pkl", "rb") as f: pickle_loaded = pickle.load(f) # 3) CSV with open("data.csv", "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["id", "name", "score"]) writer.writeheader() writer.writerows(data) with open("data.csv", "r", encoding="utf-8") as f: reader = csv.DictReader(f) csv_loaded = [ {"id": int(row["id"]), "name": row["name"], "score": float(row["score"])} for row in reader ] print(json_loaded) print(pickle_loaded) print(csv_loaded) ``` **Belangrijk** * CSV vereist expliciete type‑conversie. * Pickle is handig, maar de bron moet betrouwbaar zijn. --- ## 6. Afsluiting {#sec-f88db3766ed6} Met alleen de standaardbibliotheek kun je data opslaan en serialiseren op een breed scala aan manieren. * **Leesbaar en taaldonker** → `json` * **Exact Python‑object bewaren** → `pickle` * **Eenvoudige tabulaire export** → `csv` Kies op basis van de vorm en het doel van je data – zo wordt het proces snel en overzichtelijk.