Abschnitt 8 · Lektion 3
JSON
Ein Array in eine Datei zu schreiben klingt nach einer Aufgabe für einen Nachmittag: Trennzeichen ausdenken, Sonderfälle bedenken, Einlesefunktion bauen. Das ist alles schon erledigt, und zwar in einem Format, das außer PHP auch JavaScript, Python und jede Schnittstelle im Netz versteht.
Das Paar: json_encode und json_decode
<?php
$warenkorb = [
"kunde" => "Mia",
"artikel" => ["Kaffee", "Brot"],
"summe" => 1245,
];
$text = json_encode($warenkorb);
echo "Als Text:\n", $text, "\n";
echo "Typ: ", get_debug_type($text), "\n";
$zurueck = json_decode($text, true);
echo "\nUnd wieder zurueck:\n";
var_dump($zurueck); json_encode() macht aus deinem Array eine Zeichenkette. json_decode() macht daraus wieder ein
Array. Mehr ist es im Kern nicht, und für alles, was du in diesem Kurs speicherst, reicht dieses
Paar.
Sieh dir das Ergebnis der ersten Zeile an: Der ganze Warenkorb steht in einer Zeile, mit geschweiften Klammern für Zuordnungen und eckigen für Listen. Genau der Unterschied aus Lektion 5.2, nur diesmal sichtbar im Text.
Das zweite Argument entscheidet, was zurückkommt
<?php
$text = '{"kunde": "Mia", "summe": 1245}';
echo "Ohne zweites Argument:\n";
$objekt = json_decode($text);
var_dump($objekt);
echo "Zugriff: ", $objekt->kunde, "\n";
echo "\nMit true:\n";
$array = json_decode($text, true);
var_dump($array);
echo "Zugriff: ", $array["kunde"], "\n"; json_decode($text) gibt dir kein Array zurück, sondern ein Objekt. Der Zugriff sieht dann
$objekt->kunde aus statt $objekt["kunde"], und count(), foreach mit Schlüssel und alles
andere aus Abschnitt 5 verhält sich anders.
Objekte kennst du seit Lektion 6.7, hier willst du aber keine. Was du mit frisch gelesenen Daten
vorhast, sind die Array-Funktionen aus Abschnitt 5, und die arbeiten mit Arrays. Deshalb steht in
diesem Kurs überall true als zweites Argument, und deshalb solltest du es dir angewöhnen: Solange
du nicht ausdrücklich Objekte willst, willst du Arrays.
Damit die Datei lesbar bleibt
<?php
$daten = ["ware" => "Müsli", "menge" => 3, "bio" => true];
echo "So klein wie moeglich:\n";
echo json_encode($daten), "\n";
echo "\nMit Einrueckung:\n";
echo json_encode($daten, JSON_PRETTY_PRINT), "\n";
echo "\nMit Einrueckung und echten Umlauten:\n";
echo json_encode($daten, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), "\n"; Standardmäßig schreibt json_encode so kurz wie möglich: keine Umbrüche, keine Leerzeichen. Für
eine Übertragung übers Netz ist das richtig, für eine Datei, in die du selbst noch einmal
hineinsiehst, nicht.
Zwei Schalter helfen, und beide gehören zusammen:
JSON_PRETTY_PRINTsetzt Umbrüche und rückt mit vier Leerzeichen ein.JSON_UNESCAPED_UNICODElässt Umlaute als Umlaute stehen. Ohne den Schalter macht PHP aus demüdie Ersatzschreibweise\u00fc, ausMüsliwird alsoM\u00fcsli. Beides ist gültiges JSON und wird beim Einlesen wieder dasselbe, nur lesen kann ein Mensch nur das eine. Ohne Datei geht das auch:php -r 'echo json_encode("Müsli");'im Terminal antwortet mit"M\u00fcsli".
Der senkrechte Strich dazwischen ist derselbe wie bei den Dateischaltern in Lektion 8.1.
Wenn das JSON kaputt ist
<?php
$kaputt = '{"kunde": "Mia", "summe": }';
echo "Ohne Schalter:\n";
$still = json_decode($kaputt, true);
var_dump($still);
echo "Nachgefragt: ", json_last_error_msg(), "\n";
echo "\nMit JSON_THROW_ON_ERROR:\n";
try {
json_decode($kaputt, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $fehler) {
echo "Gefangen: ", $fehler->getMessage(), "\n";
echo "Code: ", $fehler->getCode(), "\n";
} Und jetzt der Anschluss an Abschnitt 7. Bekommt json_decode etwas, das kein gültiges JSON ist,
gibt es stillschweigend null zurück. Keine Warning, kein Fehler, nichts auf dem Fehlerkanal.
Dein Programm arbeitet mit null weiter, und der Fehler taucht drei Funktionen später als etwas
ganz anderes auf.
Um zu erfahren, was los war, müsstest du von dir aus json_last_error_msg() fragen. Genau das ist
das Muster aus Lektion 7.4: eine Antwort, die man übersehen kann, wird übersehen.
Das vierte Argument räumt damit auf. JSON_THROW_ON_ERROR macht aus dem stillen null eine
JsonException, und die kannst du fangen wie jede andere Ausnahme. Die Meldung lautet
Syntax error, der Code ist 4.
Das dritte Argument, das dazwischensteht, ist die maximale Verschachtelungstiefe. 512 ist der
Standardwert, und du schreibst ihn nur hin, weil du an das vierte herankommen willst. Wer die
Schreibweise mit den benannten Argumenten aus Lektion 6.3 vorzieht, kommt mit
json_decode($text, true, flags: JSON_THROW_ON_ERROR) zum selben Ziel.
Der ganze Weg an einem Stück
{"ort":"Regal 3","waren":[{"name":"Kaffee","menge":1}]} <?php
$daten = json_decode(file_get_contents("lager.json"), true, 512, JSON_THROW_ON_ERROR);
echo "Vorher: ", count($daten["waren"]), " Ware\n";
$daten["waren"][] = ["name" => "Müsli", "menge" => 3];
file_put_contents(
"lager.json",
json_encode($daten, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
);
echo "Nachher: ", count($daten["waren"]), " Waren\n";
echo "\nSo sieht die Datei jetzt aus:\n";
echo file_get_contents("lager.json"), "\n"; Lesen, umbauen, zurückschreiben. Das ist das Muster, mit dem eine kleine Anwendung ohne Datenbank auskommt, und es ist genau das, was du gleich in der Challenge baust.
Beachte die Reihenfolge im Beispiel: Erst wird die Datei vollständig gelesen, dann im Speicher verändert, dann in einem Rutsch zurückgeschrieben. Nicht Stück für Stück in die Datei hinein. So bleibt sie in jedem Moment gültiges JSON, und wenn zwischendrin etwas schiefgeht, steht dort noch der alte Stand.
Und weil die Datei danach anders ist als davor, fängt ein zweites php index.php im Terminal mit
zwei Waren an statt mit einer: Das Beispiel arbeitet auf dem Stand, den es selbst hinterlassen hat.
Der Prüfknopf setzt die Datei vor jedem Lauf zurück, das Terminal nicht.
Zum Mitnehmen
Ein Array lebt nur, solange dein Skript läuft. JSON ist der übliche Weg, es auf die Festplatte zu legen und beim nächsten Lauf unverändert zurückzubekommen, und zwar in einem Format, das jede andere Sprache auch versteht.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 5 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.