JSON in PowerShell erzeugen und bearbeiten

    JavaScript Object Notation (JSON)Die JavaScript Object Notation (JSON) hat sich als ein­faches Text­format für den Aus­tausch und die Seria­lisierung von Daten etabliert, unab­hängig von Platt­formen und Pro­grammier­sprachen. PowerShell spricht solche Strukturen als Objekte an und erspart dem User so das Parsen von Text­dateien.

    JSON ist neben XML, HTML und CSV ein weiteres Format, das PowerShell mit eigenen Cmdlets unterstützt. Da es relativ leicht­gewichtig ist, bietet es sich bei einigen Anwendungen als Alternative zum relativ komplexen XML an.

    Diese Eigenschaft könnte man sich zunutze machen, um Daten aus PowerShell-Scripts im JSON-Format zu speichern, sie später wieder aufzunehmen und weiter zu bearbeiten. Das gilt besonders für komplexere Strukturen wie etwa Hash-Tabellen.

    Für die Umwandlung nach JSON ist das Cmdlet ConvertTo-Json zuständig, für den umge­kehrten Weg gibt es ConvertFrom-Json.

    Ausgabe von Cmdlets als JSON speichern

    Zum Beispiel könnte man den Status aller Windows-Dienste, deren Name "remote" enthält, sowie einige zusätzliche Infos als JSON in einer Datei speichern:

    Umgekehrt ließe sich diese Datei auf diese Weise einlesen:

    $s = Get-Content -Raw -Encoding UTF8 services.json | ConvertFrom-Json

    Die in $s als Eigenschaften eines Objekts gespeicherten JSON-Elemente lassen sich einfach so ansprechen:

    $s.displayname

    Damit würde man die Anzeigenamen aller Services ausgeben.

    Ausgabe von Get-Service im JSON-Format speichern

    Konfiguration von Windows Terminal bearbeiten

    Aus der Sicht der System­verwaltung bedeutsam ist, dass sich JSON nicht nur als Format für den Daten­austausch etabliert hat, sondern immer häufiger als Syntax für Konfi­gurations­dateien verwendet wird. Beispiele dafür sind Mozilla Firefox oder Microsofts neues Windows Terminal.

    Letzteres erfordert bis dato, dass man für die Konfiguration der ver­schiedenen Kommando­zeilen die Datei profiles.json direkt bearbeitet. Anstatt dies manuell in einem Editor zu tun, könnte man zu PowerShell greifen und sich so das Hantieren mit Klammern, Kommata und Doppelpunkten ersparen.

    Die Profile in der Konfiguration folgen diesem Muster:

    Die Profile liegen somit als Array vor und jedes von ihnen wird spezifiziert durch mehrere Paare aus Name und Wert (zum Beispiel "commandline" und "powershell.exe"), die man in PowerShell als Hash-Tabelle darstellen kann.

    Profile in der Konfigurationsdatei von Windows Terminal

    Angenommen, man möchte beim ersten Profil die Kommando­zeile für powershell.exe um eine Pfad­angabe ergänzen, dann spricht man es über den Index [0] an und weist der Eigenschaft commandline einen neuen Wert zu:

    Windows Terminal unterstützt zahlreiche Optionen für eine Kommando­zeile, darunter Farben, Fonts oder Schrift­größen. In der Standard­konfiguration sind diese aber nicht explizit gesetzt, so dass eine Zuweisung nach obigem Muster

    $p.profiles[0].fontSize = "18"

    zu einer Fehlermeldung führt, wonach das Objekt über diese Eigenschaft nicht verfügt.

    Daher muss man für diesen Zweck ein eigenes Paar aus Name und Wert hinzufügen:

    $p.profiles[0] | Add-Member -Name "fontSize" -Value "18" -MemberType NoteProperty

    Möchte man hingegen eine Eigenschaft entfernen, so muss man die JSON-Repräsentation als PSObject ansprechen:

    $p.profiles[0].PSObject.Properties.Remove("fontSize")

    Neues Profil erstellen

    Eine komplexere Aufgabe bestünde darin, ein neues Profil für ein Kommando­zeilen­programm hinzu­zufügen, in unserem Beispiel für ftp.exe. Hier liegt es nahe, ein bestehendes Profil zu kopieren, anzupassen und an das vorhandene Array anzuhängen.

    Konfigurationsdatei von Windows Terminal um ein neues Profil erweitern

    Hier zeigt sich, dass man in der Praxis oft unerwartete Hürden überwinden muss, auch wenn man es scheinbar mit einem standar­disierten Format zu tun hat. So verwendet Windows Terminal in profiles.json Kommentare wie in Javascript, die einige Parser, darunter der von PowerShell, aber nicht akzeptieren. Diese muss man daher beim Einlesen ausfiltern, dafür bietet sich eine Regex an.

    Außerdem stellt sich heraus, dass das Schreiben in die JSON-Datei per Redirect, wie im obigen Beispiel praktiziert, aus der Sicht von Windows Terminal zu einer ungültigen Struktur führt. Hier muss man über Out-File sicherstellen, dass als Zeichensatz UTF-8 verwendet wird.

    Schließlich macht es PowerShell schwer, ein Array oder eines seiner Elemente zu kopieren. Zuweisungen an eine neue Variable übergeben immer nur eine Referenz, so dass sich Änderungen in der vermeint­lichen Kopie stets auch auf das ursprüng­liche Array auswirken.

    Wenn man schon mit JSON arbeitet, kann man sich damit behelfen, indem man das gewünschte Element des Arrays in diesem Format zwischens­peichert und anschließend in eine neue Variable einliest.

    JSON-Datei von Grund auf erstellen

    Mit PowerShell muss man nicht immer nur auf eine vorhandene JSON-Datei zugreifen, um diese zu modi­fizieren. Vielmehr kann man die ent­sprechende Datenstruktur neu generieren und dann als JSON serialisieren.

    Hash-Tabelle im JSON-Format serialisieren

    Dieses Beispiel erzeugt eine Hash-Tabelle $h, in die ein weiterer Hashtable N und ein Array A eingebettet sind. Während es das Array gleich mit zwei Elementen initialisiert, erhält die Hash-Tabelle zwei Name-Wert-Paare erst im Nachhinein. Ein Cast mit [ordered] stellt zudem sicher, dass die zugewiesene Reihenfolge der Elemente erhalten bleibt.

    Die Ausgabe sieht dann so aus:

    Keine Kommentare