====== std.json ======
JSON auf Textebene: Sonderzeichen maskieren, Wohlgeformtheit grob prüfen, einen Einzelwert einlesen und **flache Arrays** über ein Pipe-getrenntes Zwischenformat verarbeiten. Ein Dokumentmodell mit Objektzugriff gibt es nicht.
→ [[lyx_-_programmiersprache:units:string|std.string]] · [[lyx_-_programmiersprache:guides:daten-serialisierung|Guide: Daten & Serialisierung]] · [[lyx_-_programmiersprache:units|Standard Library]]
Alle Beispiele dieser Seite sind mit ''lyxc 1.0.21A'' übersetzt und ausgeführt; die gezeigten Ausgaben sind echte Programmausgaben.
**Einsatz:** einfache REST-Antworten auswerten, Zahlenlisten übergeben, Werte für die Ausgabe maskieren.
> **Drei der vier früheren Mängel sind weg** — nachgemessen mit ''lyxc 1.1.11B'':
>
> * ''toArray'' → ''stringify'' läuft **verlustfrei**: ''%%[1,2,3]%%'' kommt als ''%%[1,2,3]%%'' zurück, nicht als ''%%["1","2","3"]%%'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1432|#1432]]).
> * ''isValidJSON'' prüft den **Inhalt**: ''%%[abc]%%'' wird abgewiesen, ''%%[1,2]%%'' gilt als gültig ([[https://github.com/SEOLizer/LyX-Compiler/issues/1434|#1434]]).
> * ''JSONEscape'' maskiert Steuerzeichen: aus einem Tabulator wird ''\t'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1433|#1433]]).
>
> **Geblieben ist der Objektzugriff.** „Hole ''user.name'' aus diesem JSON" geht mit ''std.json'' nicht: ''parseValue'' auf ''%%{"a":1}%%'' meldet den Typ (5 = Objekt) und lässt den Zielpuffer leer ([[https://github.com/SEOLizer/LyX-Compiler/issues/1435|#1435]]). Für echte Dokumentverarbeitung führt der [[lyx_-_programmiersprache:guides:daten-serialisierung|Guide]] die gangbaren Wege auf.
----
===== Typ- und Fehlercodes =====
^ Konstante ^ Wert ^ ^ Konstante ^ Wert ^
| ''JSON_NULL'' | 0 | | ''ERR_JSON_OK'' | 0 |
| ''JSON_BOOL'' | 1 | | ''ERR_JSON_INVALID'' | 1 |
| ''JSON_NUMBER'' | 2 | | ''ERR_JSON_EXPECTED'' | 2 |
| ''JSON_STRING'' | 3 | | ''ERR_JSON_EOF'' | 3 |
| ''JSON_ARRAY'' | 4 | | ''ERR_JSON_ESCAPE'' | 4 |
| ''JSON_OBJECT'' | 5 | | | |
Die ''JSON_*''-Werte liefert ''parseValue'' als **Typ**, die ''ERR_JSON_*''-Werte liefert ''parseArray'' als **Fehlercode**. Von den fünf Fehlercodes verwendet die Unit nur ''ERR_JSON_OK'' und ''ERR_JSON_INVALID''.
> **Rückgabewerte bedeuten je Funktion etwas anderes.** ''parseArray'' gibt einen **Fehlercode** zurück (''0'' = Erfolg), ''parseValue'' einen **Typ**, ''toArray''/''stringify''/''JSONEscape'' den **Zielzeiger**. Das Ergebnis steht in allen Fällen im Zielpuffer, den der Aufrufer stellt.
----
===== Prüfen, einlesen, maskieren =====
^ Signatur ^ Beschreibung ^
| ''isValidJSON(s: pchar): bool'' | Prüft den Inhalt, nicht nur die Klammerpaare: ''%%[abc]%%'' wird abgewiesen, ''%%[1,2,3]%%'' gilt als gültig (seit #1434) |
| ''parseValue(dest, src): int64'' | Einzelwert; Rückgabe ist der ''JSON_*''-Typ, der Wert landet in ''dest'' |
| ''parseArray(dest, src): int64'' | JSON-Array ins Pipe-Format; Rückgabe ist ein ''ERR_JSON_*''-Code |
| ''toArray(dest, json_str): pchar'' | wie ''parseArray'', leert ''dest'' im Fehlerfall |
| ''JSONEscape(dest, src): pchar'' | maskiert ''"'', ''\'', Zeilenumbruch, Wagenrücklauf, Tabulator — **und setzt Anführungszeichen** |
| ''serializeValue(dest, value, json_type): pchar'' | maskiert bei ''JSON_STRING'', kopiert sonst unverändert |
| ''serializeArray(dest, src): pchar'' · ''stringify(dest, pipe_str): pchar'' | Pipe-Format zurück nach JSON (identisch) |
import std.json;
import std.alloc;
import std.string;
fn J(b: bool): pchar { if (b) { return "gueltig"; } return "ungueltig"; }
fn main(): int64 {
var d: pchar := alloc(1024) as pchar;
// Pruefen: Skalare und Arrays/Objekte werden inhaltlich geprueft (#1434)
PrintLn(StrConcat("'{\"a\":1}' ", J(isValidJSON("{\"a\":1}"c))));
PrintLn(StrConcat("'[1,2,3]' ", J(isValidJSON("[1,2,3]"c))));
PrintLn(StrConcat("'nonsense' ", J(isValidJSON("nonsense"c))));
PrintLn(StrConcat("'12.5' ", J(isValidJSON("12.5"c))));
PrintLn(StrConcat("'12.5.7' ", J(isValidJSON("12.5.7"c))));
PrintLn(StrConcat("'[abc]' ", J(isValidJSON("[abc]"c))));
// Array einlesen: der Rueckgabewert ist ein Fehlercode, das Ergebnis steht in dest
var rc: int64 := parseArray(d, "[1,2,3]"c);
PrintLn(StrConcat(StrConcat("parseArray rc=", IntToStr(rc)), StrConcat(" Pipe-Form: ", d)));
// Einzelwert einlesen: der Rueckgabewert ist der Typ
var typ: int64 := parseValue(d, "\"Hallo\""c);
PrintLn(StrConcat(StrConcat("parseValue Typ=", IntToStr(typ)), StrConcat(" Inhalt: ", d)));
// Maskieren fuer die Ausgabe
JSONEscape(d, "Er sagte \"Hallo\"\nund ging"c);
PrintLn(StrConcat("JSONEscape: ", d));
return 0;
}
'{"a":1}' gueltig
'[1,2,3]' gueltig
'nonsense' ungueltig
'12.5' gueltig
'12.5.7' ungueltig
'[abc]' ungueltig
parseArray rc=0 Pipe-Form: 1|2|3
parseValue Typ=3 Inhalt: Hallo
JSONEscape: "Er sagte \"Hallo\"\nund ging"
Die Skalarprüfung ist seit #1269 belastbar: ''nonsense'' und ''12.5.7'' werden abgewiesen, ''true''/''false''/''null'' namentlich verglichen. Nur der **Inhalt** von Arrays und Objekten bleibt ungeprüft — dort zählt allein, ob sich zur öffnenden Klammer eine schließende findet.
> **''JSONEscape'' maskiert Steuerzeichen** ([[https://github.com/SEOLizer/LyX-Compiler/issues/1433|#1433]], nachgemessen mit lyxc 1.2.2B): aus einem Tabulator wird ''\\t''. Frühere Fassungen ließen alles unter U+0020 unverändert durch und erzeugten damit ungültiges JSON.
----
===== Das Pipe-Format =====
Arrays werden nicht als Struktur geführt, sondern als eine Zeichenkette, in der die Elemente durch ''|'' getrennt sind. ''parseArray'' erzeugt sie, ''stringify'' macht daraus wieder JSON.
import std.json;
import std.alloc;
import std.string;
fn Zeig(json: pchar): void {
var pipe: pchar := alloc(1024) as pchar;
var back: pchar := alloc(1024) as pchar;
toArray(pipe, json);
stringify(back, pipe);
PrintLn(StrConcat(StrConcat(json, " -> "), StrConcat(pipe, StrConcat(" -> ", back))));
}
fn main(): int64 {
Zeig("[1,2,3]"c);
Zeig("[\"a\",\"b\"]"c);
Zeig("[1,[2,3]]"c);
Zeig("[\"a|b\",\"c\"]"c);
return 0;
}
[1,2,3] -> 1|2|3 -> [1,2,3]
["a","b"] -> "a"|"b" -> ["a","b"]
[1,[2,3]] -> 1|[2,3] -> [1,[2,3]]
["a|b","c"] -> "a\|b"|"c" -> ["a|b","c"]
> **Der Durchlauf ist verlustfrei** ([[https://github.com/SEOLizer/LyX-Compiler/issues/1432|#1432]] behoben, nachgemessen mit 1.1.14A). Alle vier früheren Mängel sind weg:
>
> - **Zahlen bleiben Zahlen**: ''%%[1,2,3]%%'' kommt als ''%%[1,2,3]%%'' zurück, nicht als ''%%["1","2","3"]%%''.
> - **Zeichenketten werden nicht doppelt maskiert**: aus ''%%["a","b"]%%'' wird wieder ''%%["a","b"]%%''.
> - **Verschachtelung bleibt Struktur**: das innere ''%%[2,3]%%'' bleibt ein Array.
> - **Ein ''|'' im Wert wird maskiert** (''a\|b'') und beim Rückweg wiederhergestellt — aus zwei Elementen werden nicht mehr drei.
>
> Ältere Fassungen dieser Seite zeigen die verlustbehaftete Ausgabe.
Die Pipe-Form lässt sich mit ''StrSplit'' aus [[lyx_-_programmiersprache:units:string|std.string]] weiterverarbeiten — das ist der vorgesehene Weg, an die einzelnen Werte zu kommen.
----
===== Einzelwerte =====
''parseValue'' erkennt den Typ am ersten Zeichen und legt den Wert in ''dest'' ab:
^ Eingabe ^ Rückgabe ^ ''dest'' ^
| ''%%"Hallo"%%'' | ''JSON_STRING'' (3) | ''Hallo'' — Anführungszeichen entfernt, Maskierungen aufgelöst |
| ''%%[1,2]%%'' | ''JSON_ARRAY'' (4) | Pipe-Form ''%%1|2%%'' |
| ''%%{"a":1}%%'' | ''JSON_OBJECT'' (5) | **unverändert** — der Puffer wird nicht angefasst |
| ''true'' / ''false'' | ''JSON_BOOL'' (1) | ''true'' / ''false'' |
| ''null'' | ''JSON_NULL'' (0) | ''null'' |
| ''42'', ''3.5'' | ''JSON_NUMBER'' (2) | die Ziffern |
| alles andere | ''JSON_NUMBER'' (2) | die Eingabe unverändert |
> **Zwei Fallen in dieser Tabelle** ([[https://github.com/SEOLizer/LyX-Compiler/issues/1435|#1435]]): Bei einem **Objekt** bleibt der Zielpuffer unberührt — dort steht dann noch, was ein vorheriger Aufruf hinterlassen hat. Und **unbekannte Eingaben werden als Zahl gemeldet**: ''Muell'' liefert ''JSON_NUMBER'' und landet unverändert im Puffer. Vor der Auswertung also den Typ prüfen **und** bei ''JSON_OBJECT'' den Puffer selbst leeren.
----
===== Fallstricke =====
* **Zielpuffer gehören dem Aufrufer** und werden nicht auf Größe geprüft. Für ''JSONEscape'' sind zwei Byte je Eingabezeichen plus zwei für die Anführungszeichen sicher.
* **''JSONEscape'' setzt die Anführungszeichen selbst** — wer sie zusätzlich schreibt, bekommt doppelte.
* **''isValidJSON'' ist keine Eingangsprüfung** für fremde Daten.
* **Kein Objektzugriff, keine Pfadausdrücke, keine Zahlen-Umwandlung** — was aus ''parseValue'' kommt, ist Text; für ''int64'' anschließend ''StrToInt'' aus [[lyx_-_programmiersprache:units:string|std.string]].
* **Kein Whitespace-Handling** zwischen Elementen: ''%%[1, 2]%%'' ergibt im Pipe-Format ''%%1| 2%%'' — mit führendem Leerzeichen im zweiten Element.
* **''serializeValue'' maskiert nur bei ''JSON_STRING''.** Für alle anderen Typen kopiert es die Eingabe wörtlich — auch dann, wenn dort etwas steht, das kein gültiges JSON ist.
----
**Weiterführend:** [[lyx_-_programmiersprache:guides:daten-serialisierung|Guide: Daten & Serialisierung]] · [[lyx_-_programmiersprache:units:string|std.string]] · [[lyx_-_programmiersprache:units:xml|std.xml]] · [[lyx_-_programmiersprache:units:net:http|std.net.http]] · [[lyx_-_programmiersprache:units|Standard Library]]
**Quelle:** ''std/json.lyx'' (480 Zeilen) · **Autor:** Andreas Röne · **Copyright:** 2024–2025 Andreas Röne
Letzte Aktualisierung: 2026-09-05 ([[https://github.com/SEOLizer/LyX-Compiler/issues/1433|#1433]], nachgemessen mit lyxc 1.2.2B) — ''JSONEscape''-Kasten auf den behobenen Stand gezogen.
Vorherige letzte Aktualisierung: 2026-08-30 — Beispielausgaben gegen ''lyxc 1.1.14A'' nachgezogen: ''isValidJSON("[abc]")'' ist jetzt ''ungueltig'' (#1434) und der Pipe-Durchlauf ist verlustfrei (#1432). Text, Tabellenzeile und Kasten entsprachen dem noch nicht.
Vorherige Aktualisierung: 2026-08-27 — die vier Fallstricke gegen ''lyxc 1.1.11B'' nachgemessen: #1432, #1433 und #1434 sind behoben, #1435 (Objektzugriff) besteht fort.
Vorherige Letzte Aktualisierung: 2026-08-13 — Seite gegen ''std/json.lyx'' überarbeitet: zwei lauffähige Beispiele mit echter Ausgabe, Rückgabewert-Bedeutungen je Funktion, Verhaltenstabelle für ''parseValue'', Grenzen des Pipe-Formats, Fallstricke. Belegt und als Issue erfasst: Pipe-Durchlauf verliert Typen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1432|#1432]]), ''JSONEscape'' maskiert keine Steuerzeichen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1433|#1433]]), ''isValidJSON'' prüft ''%%[…]%%''/''%%{…}%%'' nur auf Klammerpaare ([[https://github.com/SEOLizer/LyX-Compiler/issues/1434|#1434]]), ''parseValue'' lässt ''dest'' bei Objekten unberührt ([[https://github.com/SEOLizer/LyX-Compiler/issues/1435|#1435]]). Geprüft mit ''lyxc 1.0.21A''.
Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen).