The book is currently only available in German.
Standard-Bibliothek — `json`
Verfügbar — implementiert in Phase B.6.6. Vollständige Spec in
docs/json.md.
JSON ist das Lingua-Franca für Daten zwischen Programmen, APIs und Konfig-Dateien. Kistes json-Modul kann beide Richtungen: Text → Wert (parse) und Wert → Text (encode).
22.1 Aktivieren
nutze json
nimm daten = json.geparst("[1, 2, 3]")
sag daten // [1, 2, 3]
sag typ(daten) // liste
nimm text = json.erzeugt(daten)
sag text // "[1,2,3]"
22.2 Number-Heuristik (das Spannende!)
JSON hat eine Zahl-Form. Kiste hat drei (ganz, dezimal, komma). Die Heuristik schaut auf die JSON-Eingabe:
| JSON-Eingabe | Kiste-Typ | Begründung |
|---|---|---|
42 (Integer-Form) |
ganz |
exakt, beliebig groß |
42.5 (mit Punkt) |
dezimal |
„Ich habe 0.1 getippt → ich will exakte Dezimalrechnung" |
1e6 oder 42.0e0 (mit e) |
komma |
„Wissenschaftliche Notation → ich rechne approximativ" |
sag typ(json.geparst("42")) // ganz
sag typ(json.geparst("42.5")) // dezimal
sag typ(json.geparst("1e6")) // komma
Warum diese Heuristik? Weil sie der Anwender-Intuition folgt. Wer 0.1 schreibt, will exakte Dezimalrechnung — dezimal ist die ehrliche Wahl. Wer 1e6 schreibt, hat sich bewusst für wissenschaftliche Notation entschieden — komma ist hier richtig.
22.3 Parse: zwei Varianten
// Variante 1: wirft bei Fehler
nimm daten = json.geparst("[1, 2, 3]") // OK
nimm bumm = json.geparst("kaputt") // Fehler
// Variante 2: gibt nichts bei Fehler
nimm vielleicht = json.versucht_geparst("kaputt") // nichts
nimm gut = json.versucht_geparst("[1,2]") // [1, 2]
Wann welche? versucht_geparst ist für erwartbare Fehler — User-Eingabe, externe Daten, optionaler Lookup. geparst ist für Daten, die valid sein müssen — z.B. eine Konfig-Datei, die du selbst geschrieben hast: wenn die kaputt ist, soll das Programm laut scheitern, nicht still weitermachen.
22.4 Encode: kompakt oder schön
nimm person = {"name": "Sascha", "tags": ["admin", "geek"]}
sag json.erzeugt(person)
// {"name":"Sascha","tags":["admin","geek"]}
sag json.erzeugt_schön(person)
// {
// "name": "Sascha",
// "tags": [
// "admin",
// "geek"
// ]
// }
// Custom-Einrückung
sag json.erzeugt_schön(person, "\t") // mit Tab
sag json.erzeugt_schön(person, " ") // 4 Spaces
Seit 0.9.24 schreibt
json.erzeugtselbst gebaute Karten und Listen auch im gebauten Programm (kiste build) korrekt — vorher gelang das dort nur mit Werten ausjson.geparst.
22.4b Eine Liste von Karten aufbauen
Sammlungen gleichartiger Datensätze — die Bilder eines Sprite-Sheets, die Zeilen einer Tabelle, die Treffer einer Suche — sind in JSON ein Array von Objekten. In Kiste ist das eine Liste von Karten. Wichtig: Wer die Liste füllen will, startet sie leer. Eine Liste, die schon Karten enthält, lässt sich nachträglich nicht mehr erweitern.
nutze json
nutze liste
nimm rahmen = [] // leer starten!
für f = 0 bis 2 {
liste.hänge_an(rahmen, {"x": f * 32, "dauer": 100})
}
nimm blatt = {"frames": rahmen, "meta": {"breite": 96, "schleife": wahr}}
sag json.erzeugt_schön(blatt, " ")
Eine Liste von Karten darf auch direkt hingeschrieben werden — dann steht sie aber fest:
nimm punkte = [{"x": 0, "y": 0}, {"x": 5, "y": 3}]
sag json.erzeugt(punkte) // [{"x":0,"y":0},{"x":5,"y":3}]
Und wieder heraus geht es mit zwei Zugriffen: erst die Karte aus der Liste, dann der Schlüssel aus der Karte.
nimm punkte = [{"x": 0, "y": 0}, {"x": 5, "y": 3}]
sag punkte[0]["x"] // 0
wiederhole p in punkte {
sag "Punkt bei {p["x"]}, {p["y"]}"
}
0
Punkt bei 0, 0
Punkt bei 5, 3
Gut zu wissen — eine Karte in einer Liste wird nicht kopiert. Die Liste zeigt auf dieselbe Karte. Änderst du die Karte später, siehst du die Änderung auch über die Liste:
nimm m = {"titel": "Sonne"}
nimm werke = [m]
m["titel"] = "Mond"
sag werke[0]["titel"] // Mond — es ist dieselbe Karte
Mond
Für Listen in Listen gilt dasselbe. Zahlen, Texte und Wahrheitswerte verhalten sich anders: die werden kopiert.
22.5 Mapping-Tabelle (Kiste ↔ JSON)
| Kiste | JSON |
|---|---|
nichts |
null |
wahr / falsch |
true / false |
ganz |
Integer-Form (42) |
dezimal |
Dezimal-Form (42.5) |
komma |
Float / e-Notation |
text |
JSON-String (escaped) |
liste |
JSON-Array |
karte |
JSON-Object |
Geld |
Fehler — Konvertiere vorher zu Karte oder text |
| Funktionen, Klassen, Instanzen | Fehler — nicht serialisierbar |
| NaN / Inf | Fehler — JSON kennt das nicht |
22.6 Geld zu JSON — wie geht's?
Geld ist nicht JSON-native. Wer Geld serialisieren will, macht das explizit:
nutze geld
nutze json
nimm preis = geld.neu(19.95, "CHF")
// Variante 1: als Karte mit Betrag und Währung
nimm als_karte = {
"betrag": geld.betrag(preis),
"währung": geld.währung(preis),
}
sag json.erzeugt(als_karte)
// {"betrag":19.95,"währung":"CHF"}
// Variante 2: als Text
sag json.erzeugt(als_text(preis))
// "19.95 CHF"
Beide sind valid — die Wahl hängt davon ab, ob du beim Wieder-Lesen den Geld-Typ rekonstruieren willst (Karten-Form ist parser-freundlicher).
22.7 Roundtrip
nimm orig = {"name": "Sascha", "alter": 38}
nimm zurück = json.geparst(json.erzeugt(orig))
sag zurück["name"] // "Sascha"
sag zurück["alter"] // 38
Caveat zu Karten-Reihenfolge: JSON-Objects sind per RFC „unordered". Beim Encode behält Kiste die Insertion-Order der karte. Beim Parse geht die Original-Reihenfolge verloren — Schlüssel kommen alphabetisch sortiert raus. Wer Reihenfolge braucht, baut sie aus dem Roundtrip wieder auf (z.B. via liste von [schlüssel, wert]-Paaren).
22.8 Datei + JSON kombinieren
nutze json
nutze datei
nimm konfig = {"theme": "dunkel", "schriftgröße": 14}
datei.schreibe("config.json", json.erzeugt_schön(konfig))
// Später wieder einlesen
nimm gelesen = json.geparst(datei.inhalt("config.json"))
sag "Theme: {gelesen[\"theme\"]}"
22.9 Achtung: { und } in String-Literalen
In Kiste-Strings triggert {...} die String-Interpolation (E-018). Wenn du JSON direkt im Quelltext schreibst, musst du { und } mit Backslash escapen:
// Falsch: wird als Interpolation interpretiert
nimm s = "{\"a\":1}"
// Richtig: { und } escapen
nimm s = "\{\"a\":1\}"
In den meisten realen Fällen kommt JSON aus einer Datei oder einem Netzwerk-Aufruf — da gibt es das Problem nicht.
22.10 Was nicht in json ist
- Streaming für sehr große Dateien — kommt mit
bytes/Streaming-Phase. - JSON-Schema-Validierung — eigenes Modul.
- JSON5 / JSONC / NDJSON — andere Formate.
- Benutzer-definierte Type-Encoder (z.B. „Encode jedes
Geldautomatisch als Karte") — kann später als Optionen-Karte hinzukommen, falls Bedarf.