JSON auf der Kommandozeile verarbeiten

Aus LinuxUser 02/2021

JSON auf der Kommandozeile verarbeiten

© Sebastien Decoret, 123RF

Datenwandler

Zu den bewährten Datenaustauschformaten CSV, XML und YAML stößt nun auch noch JSON. Wir zeigen, was das Format bringt und wie man es auf der Kommandozeile bearbeitet.

Der Datenaustausch zwischen Geräten und Anwendungen ist nicht immer einfach, aber oft zwingend notwendig, damit einzelne Komponenten erfolgreich zusammenarbeiten. Dabei hilft es sehr, ein standardisiertes Format zu benutzen – möglichst Textdaten, leicht lesbar, vollständig dokumentiert, flexibel für strukturierte Daten und ohne unnützen Overhead. Dafür wurden bisher CSV, XML, YAML und JSON in den Ring geworfen, daneben das Mischformat JSONML [1] und die beiden Ergänzungen JSONP und JSONPP [2]. Anhand einer Inventarliste für einen kleinen Buchbestand aus drei Büchern stellen wir die genannten Datenformate beispielhaft kurz gegenüber.

Bei Comma-separated Values (CSV) bleiben die Daten zumeist überschaubar, doch das Format ist weder standardisiert noch besonders flexibel. In einer Datei wie der aus Listing 1 steht weder der verwendete Zeichensatz fest, noch das Trennzeichen zwischen den Spalten: In Gebrauch sind neben Kommas auch Leerzeichen, Tabulatoren, Bindestriche oder Semikola. Entsprechende Eckdaten muss man entweder vereinbaren oder aus der Datei selbst erschließen. Zudem erlaubt das Format keine verschachtelten Datensätze, Arrays oder Binärdaten.

Listing 1

CSV-Datei

Stephen Fry; The Hippopotamus; 1994
Ian Rankin; Set In Darkness; 2009
Ken Follett; The Pillars of the Earth; 1989

Die Extensible Markup Language (XML) zeigt sich im Vergleich zu CSV sehr viel strukturierter und flexibler, indem sie zum Beispiel die Datenfelder eindeutig mit einem Feldnamen in der Form <feldname>Wert</feldname> kennzeichnet (Listing 2). In der Praxis hilft es, die Feldnamen so zu wählen, dass sie einen Rückschluss auf den Inhalt zulassen. Die Reihenfolge der Felder ist in einer Ebene in der Regel variabel, und es dürfen auch Felder fehlen. Als Nachteil gilt, dass eine XML-Datei durch die Kennzeichnung der Felder deutlich anwächst.

Listing 2

XML-Datei

<inventory>
  <book>
    <author>Stephen Fry</author>
    <title>The Hippopotamus</title>
    <publication>1994</publication>
  </book>
  <book>
    <author>Ian Rankin</author>
    <title>Set In Darkness</title>
    <publication>2009</publication>
  </book>
  <book>
    <author>Ken Follett</author>
    <title>The Pillars of the Earth</title>
    <publication>1989</publication>
  </book>
</inventory>

YAML steht als Akronym für YAML Ain’t Markup Language [3]. Es beschreibt auf sehr kompakte Art und Weise, wie Daten serialisiert werden. Als Grundlage dafür dienen Bindestriche und Einrückungen mittels Leerzeichen. Anleihen nimmt YAML bei XML sowie der Form, in der die drei Programmiersprachen Python, Perl und C Datenstrukturen beschreiben. Listing 3 zeigt den Buchbestand als YAML-Struktur.

Listing 3

YAML-Datei

---
book:
- author: Stephen Fry
  title: The Hippopotamus
  publication: '1994'
- author: Ian Rankin
  title: Set In Darkness
  publication: '2009'
- author: Ken Follett
  title: The Pillars of the Earth
  publication: '1989'

Hinweis

CSV, XML, YAML und JSON lassen sich nicht immer konfliktfrei und vollständig ineinander überführen.

Die Java Script Object Notation (JSON [4]) lehnt sich hingegen an Javascript an. Das Format gilt ebenfalls als sehr kompakt und flexibel. Im Unterschied zu YAML kennzeichnet JSON Objekte und deren Attribute explizit, wohingegen bei YAML die Zuordnung aus dem Kontext der Einrückungstiefe erfolgt. Die Schreibweise von JSON ist analog zu Objekten, Records oder Dictionaries – je nachdem, wie diese Struktur in ihrer Lieblingsprogrammiersprache gerade heißt.

Die einzelnen Strukturebenen kennzeichnen Sie durch Klammern und Einrückung für bessere Lesbarkeit (Listing 4). Dabei bilden Paare aus geschweiftem Klammern ({ und }) jeweils eine Einheit. Mit eckigen Klammern ([ und ]) kennzeichnen Sie Felder (auch Arrays genannt). Einzelne Feldelemente folgen der Form einer Aufzählung und werden mittels Komma separiert. Jedes Feldelement besteht aus einem Schlüssel-Wert-Paar, die jeweils ein Doppelpunkt : voneinander trennt.

Listing 4

JSON-Datei

{"book": [
  {
    "author": "Stephen Fry",
    "title": "The Hippopotamus",
    "publication": "1994"
  },
  {
    "author": "Ian Rankin",
    "title": "Set In Darkness",
    "publication": "2009"
  },
  {
    "author": "Ken Follett",
    "title": "The Pillars of the Earth",
    "publication": "1989"
  }
]}

Woher kommt JSON?

JSON steht als Akronym für Java Script Object Notation. Das kompakte Datenformat leitet sich aus der Skriptsprache Javascript ab. Die ursprüngliche Idee hinter der Entwicklung Anfang der 2000er-Jahre war der Datenaustausch zwischen Webapplikationen. Das glückte recht gut, auch wenn es sich nicht immer eindeutig parsen lässt [5]. Zur Strukturierung der Daten greift JSON auf Konventionen zurück, die jedem vertraut sind, der in C-basierten Sprachen entwickelt (C, C++, C#, Java, Javascript, Perl, Python und andere).

Mittlerweile stehen Implementierungen sowie Parser und Generatoren für alle gängigen Programmiersprachen bereit. Spezifiziert wird JSON gemäß RFC 8259 [6] und ECMA-404 [7], gängige Erweiterungen sind JSONP (JSON mit Padding), JSONPP (JSON mit Padding und Parametern) sowie JSONML. Letzteres kombiniert XML und JSON miteinander. Als Zeichensatz für alle JSON-Formate fungiert Unicode (UTF-8), womit das lustige Zeichensatzraten entfällt, wie man es von CSV her kennt.

Kleinere Datenmengen lassen sich im JSON-Format flink zwischen Anwendungen austauschen. Nimmt das übertragene Datenvolumen jedoch zu, beispielsweise bei Millionen Messpunkten eines Sensors, gehen Javascript-basierte Python-Bibliotheken wie Ipywidgets, Bokeh und Plotly häufig in die Knie. Daher bieten diese zusätzliche binäre Transportmechanismen an, um die Last abzufangen.

JSON in der Praxis

Wie bereits erwähnt, dient JSON zum Datenaustausch zwischen Anwendungen. Im Alltag finden Sie das Format beispielsweise bei Jupyter Notebooks [8], in geografischen Angaben wie GeoJSON [9] (Listing 5) oder auch Datenbanken wie MongoDB [10].

Listing 5

GEOJson-Datei

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  },
  "properties": {
    "name": "Dinagat Islands"
  }
}

Werkzeuge in der Übersicht

Nun stellen wir Ihnen eine Reihe von Werkzeugen für die Kommandozeile vor, mit denen Sie JSON-Daten hübsch ausgeben, parsen und gekonnt weiterverarbeiten. Die Tabelle “JSON-Werkzeuge” fasst die Tools zusammen. Alle stehen als Paket für Debian GNU/Linux, Ubuntu, Devuan, Linux Mint und MacOS zur Verfügung. Die Tabelle umfasst den Namen des Werkzeugs, die Programmiersprache, in der es geschrieben wurde, sowie in der letzten Spalte eine kurze Beschreibung des Einsatzzwecks.

Werkzeug

Sprache

Einsatzbereich

Aeson-pretty [11]

Haskell

JSON hübsch ausgeben

Jc [12]

Python

Ausgaben nach JSON überführen

Jid [13]

Go

JSON interaktiv filtern

Jo [14]

C

JSON-Ausgabe von der Shell

Jq [15]

C

JSON hübsch ausgeben und filtern

Jshon [16]

C

JSON lesen und erzeugen

Jsonlint [17]

PHP

JSON-Daten validieren

Nicht alle genannten Werkzeuge sind sofort verständlich und entfalten ihre volle Wirkung mitunter erst in einem bestimmten Zusammenhang. Daher haben wir die Werkzeuge anhand ihrer Funktionen gruppiert. Mehr Infos zur Verwendung finden Sie in passenden Spickzetteln, beispielsweise dem von Jq [18].

JSON gut lesbar ausgeben

Beim Pretty-Printing haben Aeson-pretty, Jc, Jo, Jq und Jshon ihren Auftritt. Während Aeson-pretty und Jq das von sich aus erledigen, helfen Sie bei den anderen Werkzeugen erst mit dem passenden Schalter nach, beispielsweise mit -p bei Jo.

In Listing 6 arbeiten Cat und Aeson-pretty für die lesbare Ausgabe über eine Pipe zusammen. Jq liefert mit folgendem Aufruf dasselbe Ergebnis, jedoch erfolgt die Ausgabe gleich farbig (Abbildung 1):

$ jq . inventar-buchbestand.json

Listing 6

JSON mit Aeson-pretty ausgeben

$ cat inventar-buchbestand.json | aeson-pretty
{
  "book": [
    {
      "publication": "1994",
      "author": "Stephen Fry",
      "title": "The Hippopotamus"
    },
    {
      "publication": "2009",
      "author": "Ian Rankin",
      "title": "Set In Darkness"
    },
    {
      "publication": "1989",
      "author": "Ken Follett",
      "title": "The Pillars of the Earth"
    }
  ]
}
$

Abbildung 1: Das Tool Jq f&auml;rbt die JSON-Ausgabe bunt und somit &uuml;bersichtlich ein.

Abbildung 1: Das Tool Jq färbt die JSON-Ausgabe bunt und somit übersichtlich ein.

Der Punkt im Aufruf von Jq erschließt sich nicht sofort. Er steht für den zu verarbeitenden Ausdruck, hier bezeichnet er alle Objekte in der als Parameter angegebenen JSON-Datei. Weitere Möglichkeiten zu einer differenzierten Filterung erklären wir im Folgenden noch. Ein explizites Einfärben der Ausgabe steuern Sie über die beiden Schalter -C (--colour-output) und -M (--monochrome-output). Ersterer schaltet die Einfärbung ein, der andere explizit ab.

Das Gegenstück dazu ist die kompakte Ausgabe mit möglichst wenigen (Leer-)Zeichen. Das beherrschen wiederum die Werkzeuge Aeson-pretty, Jc, Jo, Jq und Jshon. In Listing 7 haben wir den Aufruf von Aeson-pretty um den entsprechenden Parameter -c (--compact) ergänzt. Damit verringert sich die Anzahl Zeichen in der Ausgabe um 45 Prozent von 428 auf 236 Byte. Im Vergleich zu Listing 5 und Listing 6 übermittelt das Ergebnis immer noch dieselbe Information, jedoch nur mit der Hälfte der Datenmenge.

Listing 7

Kompakte Ausgabe mit Aeson-pretty

$ cat inventar-buchbestand.json | aeson-pretty -c
{"book":[{"publication":"1994","author":"Stephen Fry","title":"The Hippopotamus"},{"publication":"2009","author":"Ian Rankin","title":"Set In Darkness"},{"publication":"1989","author":"Ken Follett","title":"The Pillars of the Earth"}]}

JSON-Daten auf Korrektheit überprüfen

Die formatierte Ausgabe mittels Jq oder Aeson-pretty hilft meistens schon, gröbere Fehler in der JSON-Struktur auf einen Blick zu entdecken. Fiese Stellen wie fehlende Kommas verstecken sich besser, lassen sich aber mit einem Tool wie Jsonlint identifizieren. Das Werkzeug erwartet als Parameter die Datei mit den JSON-Daten. Ist alles korrekt, meldet es sich mit Valid JSON zurück. Im Fehlerfall gibt es die Stelle aus, die es als Fehler ausgemacht hat. Abbildung 2 zeigt das für den Buchbestand – erst mit einer korrekten JSON-Datei, und danach mit einer Variante, bei der ein Komma als Trennzeichen fehlt.

Abbildung 2: Fehler in JSON-Daten lassen sich mit Jsonlint recht einfach ausmachen.

Abbildung 2: Fehler in JSON-Daten lassen sich mit Jsonlint recht einfach ausmachen.

Jsonlint wurde in der Programmiersprache PHP geschrieben. Falls Sie nach einer Alternative für das Programm suchen, können Sie sich im Notfall auch mit Jq behelfen. Scheitert Jq beim Parsen der JSON-Daten, liefert das Tool als Rückgabewert eine Zahl größer null, ansonsten eben null. Listing 8 zeigt die Ausgabe für den (provozierten) Fehlerfall.

Listing 8

Fehler im JSON-Daten mit Jq finden

$ cat inventar-buchbestand-defekt.json | jq .
parse error: Expected separator between values at line 7, column 5
$ echo $?
4

Ausgaben nach JSON überführen

Alle Unix/Linux-Werkzeuge haben ihr eigenes, spezifisches Ausgabeformat. Mit einer geschickten Kombination aus Grep, Sed und Awk zerlegen Sie die Ausgabe in das Format, das Sie zur weiteren Verarbeitung benötigen. Das klingt einfach, erinnert aber oft an Treppensteigen im Rückwärtsgang mit gleichzeitigem Balancieren einer Kristallvase auf dem Kopf.

Hätte jedes Unix/Linux-Werkzeug hingegen einen Schalter --json und würde darüber seine Ausgabe im JSON-Format bereitstellen, ließen sich die Ausgaben zum einen standardisiert parsen. Zum anderen könnte es die Akzeptanz für die Nutzung der Kommandozeile steigern. Bis dahin ist der Weg jedoch noch weit, und daher bedarf es eines Provisoriums. Hier kommen die beiden Werkzeuge Jc und Jo ins Spiel – beide lesen die Ausgabe des jeweiligen Werkzeugs, wandeln die Ausgabe um, und kippen sie im JSON-Format wieder auf die Standardausgabe.

Die Liste der Ausgabeformate, die Jc bislang versteht, ist recht lang und umfasst beispielsweise die Ausgaben von Df, Du, Lsblk, Crontab, Netstat und Lsof. Abbildung 3 zeigt das für das Kommando Route. Genutzt wird hier die Ausprobierseite [19], in der Sie oben zunächst das gewünschte Unix/Linux-Kommando oder Datenformat auswählen und danach in das Eingabefeld die dazugehörige Ausgabe kopieren. Ein Klick auf den Knopf Convert to JSON erzeugt die Ausgabe darunter – jeder Eintrag ein JSON-Element. Über die Checkbox Pretty Print legen Sie fest, ob die Ausgabe ein kompakter Einzeiler oder eine aufgehübschte, länglichere Fassung werden soll.

Abbildung 3: Die Demo-App zeigt am Beispiel von Route die ins JSON-Format umgewandelte Ausgabe.

Abbildung 3: Die Demo-App zeigt am Beispiel von Route die ins JSON-Format umgewandelte Ausgabe.

Komplizierte JSON-Dateien selbst bauen und Klammern nachzählen – das war gestern. Heute übernimmt das Jo für Sie. Es erwartet die Schlüssel-Wert-Paare als Parameter und schraubt daraus eine entsprechende JSON-Ausgabe zusammen. Abbildung 4 zeigt das für die beiden Parameter zeitschrift und ausgabe.

Abbildung 4: Mit Jo bauen Sie ohne gro&szlig;en Aufwand &uuml;bersichtliche JSON-Ausgaben zusammen.

Abbildung 4: Mit Jo bauen Sie ohne großen Aufwand übersichtliche JSON-Ausgaben zusammen.

Da Jo die Schlüssel-Wert-Paare als Parameter beim Aufruf erhält, sind auch Variableninhalte aus der Shell kein Problem mehr. Listing 9 zeigt das für das aktuelle Datum und das Home-Verzeichnis, das es über die Variable $HOME in den Datensatz integriert.

Listing 9

Umgebungsvariablen einbeziehen

$ jo zeitpunkt="$(date +%c" home=$HOME
{"zeitpunkt":"Mon 12 Okt 2020 17:06:30 CEST","home":"/home/frank"}

(Interaktiv) Filtern

Bislang haben Sie stets alle Daten ausgegeben. Benötigen Sie nur ausgewählte Elemente daraus, kommen Programme ins Spiel, die auch filtern können. In diese Kategorie gehören Jq, Jid und Jshon.

Bereits weiter oben hatten wir Jq am Wickel und ließen mittels . den gesamten Datensatz ausgeben. Mit dem passenden Aufruf filtern Sie die Daten und ziehen lediglich alle Angaben zur Veröffentlichung der Bücher aus der JSON-Datei: Mit .book[] grenzen Sie die Suche zunächst auf die Bücherliste ein; daraus filtern Sie über | alle Elemente mit dem Schlüssel publication.

Abbildung 5 zeigt das Ergebnis. Zur Ausgabe dient hier die Spielwiese Jqplay – einfache Formulare im Webbrowser, deren Inhalt an Jq zur Verarbeitung weitergereicht werden. Ändern Sie den Filter oder die Ausgabe in den beiden Eingabefeldern auf der linken Seite, passt sich die Ausgabe auf der rechten Seite an.

Abbildung 5: Bei Bedarf lassen sich Jq auch JSON-Ausgaben nach beliebigen Kriterien filtern.

Abbildung 5: Bei Bedarf lassen sich Jq auch JSON-Ausgaben nach beliebigen Kriterien filtern.

Der Name Jid steht als Kürzel für JSON Interactive Digger. Mit dem Aufruf cat inventar-buchbestand.json | jid durchstöbern Sie damit interaktiv eine JSON-Datei.

Und weiter?

Spezielle Programme mit grafischen Oberflächen für das Bearbeiten von JSON-Daten haben wir bislang nicht entdeckt. Alle Texteditoren bieten eine Syntaxhervorhebung und vereinfachen damit das Editieren. Zu überzeugen wusste insbesondere der webbasierte Editor JsonViewer [20], der neben einer objektbasierten Darstellung auch eine Graphstruktur anbietet. Für Abbildung 6 haben wir ihn mit unserer Bücherliste gefüttert.

Abbildung 6: Abb. 6: Der webbasierte JsonViewer zeigt die Verkn&uuml;pfung der Daten als Graph an.

Abbildung 6: Abb. 6: Der webbasierte JsonViewer zeigt die Verknüpfung der Daten als Graph an.

JSON als Format ist klein, praktisch und erlaubt einen flinken Austausch zwischen Anwendungen. Spricht Ihr Wunschprogramm kein JSON, stehen Übersetzer wie Jc bereit, um Ihnen hier zu helfen. Bleibt noch das Lesen und Schreiben von JSON-Dateien aus Programmen heraus. Welche Bibliotheken hierfür in den einzelnen Programmiersprachen bereitstehen und wie Sie diese ansprechen, beschreiben wir in unserem Folgebeitrag in der nächsten Ausgabe. (cla/jlu)

Der Autor

Frank Hofmann arbeitet zumeist von unterwegs aus als Entwickler, Trainer und Autor. Bevorzugte Arbeitsorte sind Berlin, Genf und Kapstadt. Er gehört zu den Verfassern des Debian-Paketmanagement-Buches.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 02/2021 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben