JSON streaming
Unter der Bezeichnung JSON streaming werden verschiedene Verfahren zusammengefasst, die es ermöglichen, JSON-kodierte Daten bereits während Übertragung zu verarbeiten oder bereits gesendete oder geschriebene (und nicht mehr veränderbare) Daten zu ergänzen.
Problembeschreibung
Um mehrere Daten (üblicherweise gleichen Typs) zu einer Einheit zusammenzufassen, gibt es in JSON den Datentyp Array
. Ein JSON Array beginnt mit einer öffnenden eckigen Klammer, gefolgt von den Array-Elementen, welche durch Kommas voneinander getrennt werden und endet mit einer schließenden eckigen Klammer:
[
Element1 ,
Element2 ,
… ]
Dieses Format ist allerdings nicht „streaming-fähig“, denn ein JSON-Parser akzeptiert das Array erst mit der schließenden eckigen Klammer und kann es nicht vorher verarbeiten. Ein einmal geschlossenes Array kann aber nicht im Nachhinein wieder „geöffnet“ oder erweitert werden.
Lösungsmöglichkeiten
Das oben beschriebene Problem lässt sich auf unterschiedliche Weise lösen:
Laxerer Parser
Der Parser im Empfänger könnte die Elemente des Arrays bereits verarbeiten, sobald er das Ende des Elementes eindeutig erkannt hat:
- Zeichenketten, Objekte und Arrays beim schließenden Anführungszeichen bzw. der schließenden Klammer
null
,true
,false
und Zahlen beim ersten Zeichen, nach diesem Wert (üblicherweise ein Leerzeichen, Zeilenumbruch oder Komma)
Problematisch ist dieses Vorgehen, wenn es passieren kann, dass das Array nie geschlossen wird oder ungültige Zeichen enthält, da dann eigentlich das gesamte Array hätte verworfen werden müssen, da es kein gültiges JSON darstellt.
Line-delimited JSON
JSON ist ein textuelles Format, das unterschiedliche Formatierungen erlaubt. So können insbesondere komplexere Datenobjekte durch Leerzeichen und Zeilenumbrüche an geeigneten Stellen leichter „menschenlesbar“ formatiert werden. Umgekehrt kann die Darstellung so kompaktiert werden, dass ein Datenelement keine Zeilenumbrüche enthält (Zeilenumbrüche innerhalb von Zeichenketten müssen sowieso durch \n
kodiert werden).
Haben sich Sender und Empfänger auf derartig „einzeilig“ formatierte Datenelemente geeinigt, kann das Zeilenendezeichen als Trennzeichen verwendet werden:
{"id":123, "name":"Jane Doe", "value":4711}
{"id":666, "name":"E. Teufel", "value":-1}
Dieses Format wird von verschiedenen JavaScript-Frameworks verwendet und ist auch unter dem Namen LDJSON, NDJSON oder JSONL bekannt.
Pro Dieses Format erlaubt die Verarbeitung durch Programme, die Daten zeilenweise verarbeiten, ohne sich um den Inhalt der Zeilen zu kümmern.
Kontra Die einzelnen Datenobjekte müssen ggf. umformatiert werden, damit sie selbst keine Zeilenumbrüche enthalten.
Record-separator delimited JSON
Als Textformat darf JSON (außer den Zeichen 09hex (Tab), 0Ahex (Newline) und 0Chex (CR)) keine ASCII-Steuerzeichen enthalten. Etwaige Steuerzeichen in Zeichenketten müssen durch entsprechende Escape-Sequenzen ersetzt werden.
Somit ist es (als inkompatible Erweiterung) möglich, ein spezielles ASCII-Steuerzeichen als Trennzeichen für die einzelnen Datenelemente zu definieren.
Üblicherweise wird dafür das Zeichen 1Ehex genommen, dessen Name “Record Separator” daran erinnert, dass es ursprünglich auch als Trennzeichen für strukturierte Daten vorgesehen war.
Dieses Format wird auch JSON Text sequences genannt, hat einen eigenen MIME-Type application/json-seq
und ist im RFC 7464 spezifiziert. Hierbei wird das RS-Zeichen allerdings nicht als Trennzeichen zwischen den Einträgen verwendet, sondern als Startzeichen am Anfang eines jeden Eintrages. Nach jedem Eintrag wird außerdem ein Zeilenumbruch eingefügt, wobei man beim Parsen beachten muss, dass auch innerhalb eines Eintrags weitere Zeilenumbrüche auftreten können.
Kontra Erfordert angepasste Parser und Generatoren.
Pro Die einzelnen Datenelemente müssen nicht aufwändig umformatiert werden, sondern können 1:1 aus anderen JSON-Quellen übernommen werden
Pro Eine Vorverarbeitung, die die einzelnen Einträge voneinander trennt, erfordert nur das Scannen nach dem RS-Zeichen und ist somit sehr einfach möglich.
Concatenated JSON
Die Datenelemente werden ohne jegliche Trennzeichen direkt hintereinander übertragen. Für Zeichenketten, Arrays und Objekte stellt das für geeignete Parser kein Problem dar, andere Datentypen erfordern wenigstens ein Leerzeichen oder Zeilenumbruch, um die Daten verarbeiten zu können.
Üblicherweise wird einfach nach jedem Datenelement ein Zeilenumbruch gesendet, auch dann, wenn es nicht zum eindeutigen Parsen nötig wäre.
Pro Die meisten JSON-Parser sind ohne Weiteres bereits in der Lage, mehrere JSON-Datenelemente aus einem Datenstrom zu lesen.
Kontra Es ist nicht möglich, die einzelnen Datenelemente in einem Vorverarbeitungsschritt voneinander zu trennen, ohne das komplette JSON-Format zu parsen.