Een document lezen
Maak read_document(path): lees het UTF8 JSON-document als Python-waarde en laat JSONDecodeError door bij ongeldige inhoud. Verander het bestand niet.
Een instellingenbestand heeft meer structuur dan een platte tabel: een naam, een aan-uitkeuze en een lijst favoriete plekken. Je wilt die waarden bewaren en later als dezelfde soorten waarden terugkrijgen. JSON is geschikt voor zulke kleine, geneste documenten.
JSON beschrijft onder andere objecten, arrays, strings, getallen, booleans en null. In Python lees je die meestal als dictionaries, lijsten, strings, getallen, True of False en None. De schrijfwijze in het bestand is dus niet hetzelfde als Python-broncode.
De module json heeft twee handige paren functies. load leest uit een geopende tekststream en dump schrijft naar een stream. De varianten loads en dumps werken met een string; de laatste letter verwijst naar die stringvorm.
Voor één keuze lees je eerst de dictionary en wijzig je alleen de bedoelde sleutel. Het volgende voorbeeld schrijft daarna het hele document terug en leest het opnieuw: de naam en minuten blijven behouden. Open dus nooit alvast met w voordat het oude document succesvol is gelezen.
{"stop":"Café","open":true,"later":null,"minutes":[0,8]}import json
with open("route.json", encoding="utf-8") as stream:
route = json.load(stream)
print(route["stop"])
print(route["open"], route["later"])
print(sum(route["minutes"]))
route["open"] = False
with open("route.json", "w", encoding="utf-8") as stream:
json.dump(route, stream, ensure_ascii=False)
with open("route.json", encoding="utf-8") as stream:
saved = json.load(stream)
print(saved["open"], saved["stop"], sum(saved["minutes"]))Café True None 8 False Café 8
Let op true en null in het bestand tegenover True en None in de uitvoer. De parser doet die omzetting; je hoeft woorden niet zelf te vervangen. Een string met een nul blijft bovendien iets anders dan het getal nul of de boolean false.
Open een uitvoerbestand in modus w met UTF8 en geef de waarde aan json.dump. Met ensure_ascii=False blijft bijvoorbeeld café leesbaar als gewone tekst in het bestand. Standaard mag de encoder dezelfde letters ook als Unicode-escapes schrijven; beide vormen betekenen dezelfde waarde.
Schrijf één compleet document, geen losse documenten achter elkaar met a. Twee dictionaries direct achter elkaar vormen samen geen geldige JSON-waarde. Een inspringing met indent kan helpen bij het lezen, maar verandert de gegevens niet.
Bij vergelijken kijken we naar de ingelezen waarde. De volgorde van objectvelden en witruimte rondom komma's bepalen die betekenis niet. De volgorde van een lijst hoort juist wél bij de gegevens en moet behouden blijven.
{"stop": }import json
from pathlib import Path
before = Path("kapot.json").read_bytes()
for name in ["kapot.json", "niet-aanwezig.json"]:
try:
with open(name, encoding="utf-8") as stream:
settings = json.load(stream)
settings["open"] = False
with open(name, "w", encoding="utf-8") as stream:
json.dump(settings, stream)
except json.JSONDecodeError:
print("bestand bestaat, inhoud klopt niet")
except FileNotFoundError:
print("bestand ontbreekt")
print(Path("kapot.json").read_bytes() == before)
print(Path("niet-aanwezig.json").exists())bestand bestaat, inhoud klopt niet bestand ontbreekt True False
Een JSONDecodeError zegt dat de aanwezige tekst niet als geldig JSON-document gelezen kan worden. Een FileNotFoundError zegt dat het openen al misging doordat het bestand ontbreekt. Vang alleen die tweede fout wanneer je bij een eerste start een standaardwaarde wilt gebruiken.
Een bestaande lege dictionary of false is een geldige inhoud. Met result or fallback vervang je zulke geldige waarden onterecht. Geef de fallback uitsluitend terug in de afgesproken ontbrekend-bestandtak en laat andere fouten zichtbaar.
Alles in één brede except Exception stoppen maakt een beschadigd instellingenbestand onzichtbaar. Je programma lijkt met standaardinstellingen te werken, terwijl gegevens verloren zijn geraakt. Een gerichte except houdt het onderscheid uit het voorbeeld intact.
Voor één instelling lees je eerst de bestaande dictionary, pas je één sleutel aan en schrijf je het document terug. Behoud alle andere velden en lees het oude document voordat je het voor schrijven opent. Deze simpele aanpak is nog geen bescherming tegen een schrijffout of twee gelijktijdige schrijvers; veilig vervangen komt later in deze module.
Maak read_document(path): lees het UTF8 JSON-document als Python-waarde en laat JSONDecodeError door bij ongeldige inhoud. Verander het bestand niet.
Maak write_document(path, data): vervang het bestand door één geldig JSON-document met gewone Unicode-letters (ensure_ascii=False). Behoud typen en lijstvolgorde, verander data niet en geef None terug.
Maak read_or_default(path, fallback): lees normaal het document, maar geef bij FileNotFoundError exact het meegegeven fallback-object terug. Laat JSONDecodeError en IsADirectoryError door; wijzig fallback niet.
Maak set_option(path, key, value): lees de bestaande JSON-dictionary, zet die sleutel op value en schrijf het document terug. Behoud andere velden en geef None. Ongeldige oude inhoud blijft ongewijzigd met JSONDecodeError.
Hierna zoeken en ordenen we bestanden in mappen.
Voer je code uit en ontdek
wat je hebt gemaakt.
Je hoeft het niet in één keer goed te doen. Na het uitvoeren zie je hier welke stappen al kloppen.