PowerShell and JSON

JSON is something that’s being used a lot, it’s easy for storing and retrieving data. In this small blog post, I will show you how to do that 🙂

What is JSON?

JSON (JavaScript Object Notation) is an open standard file format and data interchange format that uses human-readable text to store and transmit data objects consisting of attribute-value pairs and arrays (or other serializable values). It is a common data format with diverse uses in electronic data interchange, including that of web applications with servers. (Source: Wikipedia)

How do you pronounce it?

Saw a video about that a while back, ‘How To Pronounce JSON by Douglas Crockford’ (The inventor of JSON) which you can find here. Two quotes from that video:

Almost everybody was saying “Jay-Sawn”, which is fine.

and

I think the correct pronunciation is probably “shason”

Reading JSON files in PowerShell

You can read JSON files by using something like this:

$JSON=Get-Content .\install_apps.json | ConvertFrom-Json

In this example, I retrieved the contents of the install_apps.json file. When opened in Notepad that looks like this:

{
   "Apps": [
      "Microsoft.SQLServerManagementStudio",
      "7zip.7zip",
      "Adobe.Acrobat.Reader.64-bit",
      "AnyConnect",
      "BraveSoftware.BraveBrowser",
      "Canonical.Ubuntu",
      "Cisco.CiscoWebexMeetings",
      "Citrix.Workspace",
      "Famatech.AdvancedIPScanner",
      "Fortinet.FortiClientVPN",
      "Git.Git",
      "GitHub.GitHubDesktop",
      "Google.Chrome",
      "Graphviz.Graphviz",
      "Insecure.Nmap",
      "JAMSoftware.TreeSize.Free",
      "Microsoft.AzureCLI",
      "Microsoft.AzureStorageExplorer",
      "Microsoft.DeploymentToolkit",
      "Microsoft.dotnetRuntime.3.1",
      "Microsoft.dotnetRuntime.5",
      "Microsoft.EdgeWebView2Runtime",
      "Microsoft.PowerBI",
      "Microsoft.Powershell",
      "Microsoft.PowerToys",
      "Microsoft.RemoteDesktopClient",
      "Microsoft.VisualStudioCode",
      "Microsoft.WindowsAdminCenter",
      "Microsoft.WindowsADK",
      "Microsoft.WindowsTerminal",
      "Mozilla.FireFox",
      "Notepad++.Notepad++",
      "Obsidian.Obsidian",
      "Ookla.Speedtest",
      "OpenVPNTechnologies.OpenVPNConnect",
      "Oracle.JavaRuntimeEnvironment",
      "PuTTY.PuTTY",
      "Python.Python.3",
      "Rufus.Rufus",
      "Teamviewer.Teamviewer",
      "Telerik.Fiddler",
      "WinSCP.WinSCP",
      "WiresharkFoundation.Wireshark",
      "Zoom.Zoom"
   ],
   "Features": [
      "Containers-DisposableClientVM",
      "Microsoft-Windows-Subsystem-Linux",
      "TelnetClient",
      "TFTP"
......

When imported in the $JSON variable, it looks like this:

Apps               : {Microsoft.SQLServerManagementStudio, 7zip.7zip, Adobe.Acrobat.Reader.64-bit, AnyConnect…}
Features           : {Containers-DisposableClientVM, Microsoft-Windows-Subsystem-Linux, TelnetClient, TFTP}
FilesToClean       : {*.lnk, desktop.ini}
MicrosftVCRuntime  : {Microsoft.VC++2008Redist-x86, Microsoft.VC++2008Redist-x64, Microsoft.VC++2010Redist-x64, Microsoft.VC++2010Redist-x86…}
ProcessesToKill    : {advanced_ip_scanner, OpenVPNConnect, PowerToys.Settings, PtSrv…}
PowerShellCommands : {Update-Help -Confirm:$False -Force:$True -ErrorAction:SilentlyContinue}
PowerShellModules  : {AIPService, Az, Azure.AnalysisServices, Azure.Storage…}
PowerShellProfile  : {Import-Module Posh-Git, Set-PSReadlineKeyHandler -Key Tab -Function Complete, Set-PSReadLineOption -PredictionSource History, [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12}
RSATTools          : {Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0, Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0, Rsat.CertificateServices.Tools~~~~0.0.1.0, Rsat.DHCP.Tools~~~~0.0.1.0…}

It has multiple attributes (Apps, Features, FilesToClean, etc. ) and $JSON.Apps will look like this:

Microsoft.SQLServerManagementStudio
7zip.7zip
Adobe.Acrobat.Reader.64-bit
AnyConnect
BraveSoftware.BraveBrowser
Canonical.Ubuntu
Cisco.CiscoWebexMeetings
Citrix.Workspace
Famatech.AdvancedIPScanner
Fortinet.FortiClientVPN
Git.Git
GitHub.GitHubDesktop
Google.Chrome
Graphviz.Graphviz
Insecure.Nmap
JAMSoftware.TreeSize.Free
Microsoft.AzureCLI
Microsoft.AzureStorageExplorer
Microsoft.DeploymentToolkit
Microsoft.dotnetRuntime.3.1
Microsoft.dotnetRuntime.5
Microsoft.EdgeWebView2Runtime
Microsoft.PowerBI
Microsoft.Powershell
Microsoft.PowerToys
Microsoft.RemoteDesktopClient
Microsoft.VisualStudioCode
Microsoft.WindowsAdminCenter
Microsoft.WindowsADK
Microsoft.WindowsTerminal
Mozilla.FireFox
Notepad++.Notepad++
Obsidian.Obsidian
Ookla.Speedtest
OpenVPNTechnologies.OpenVPNConnect
Oracle.JavaRuntimeEnvironment
PuTTY.PuTTY
Python.Python.3
Rufus.Rufus
Teamviewer.Teamviewer
Telerik.Fiddler
WinSCP.WinSCP
WiresharkFoundation.Wireshark
Zoom.Zoom

But this was just a simple attribute and value JSON file, in the example below I read the contents of an Intune backup for an Endpoint Manager Win32 App. This looks like this:

@odata.context                  : https://graph.microsoft.com/beta/$metadata#deviceAppManagement/mobileApps/$entity
@odata.type                     : #microsoft.graph.win32LobApp
id                              : 3f0f40a3-4600-4647-b04f-9457ee036b41
displayName                     : VMware Tools
description                     : VMware Tools
publisher                       : VMware
largeIcon                       :
createdDateTime                 : 15-1-2022 16:07:18
lastModifiedDateTime            : 31-3-2022 15:52:20
isFeatured                      : False
privacyInformationUrl           :
informationUrl                  :
owner                           :
developer                       :
notes                           :
uploadState                     : 1
publishingState                 : published
isAssigned                      : False
roleScopeTagIds                 : {0}
dependentAppCount               : 0
supersedingAppCount             : 0
supersededAppCount              : 0
committedContentVersion         : 1
fileName                        : install.intunewin
size                            : 129835696
installCommandLine              : install.cmd
uninstallCommandLine            : uninstall.cmd
applicableArchitectures         : x86,x64
minimumFreeDiskSpaceInMB        :
minimumMemoryInMB               :
minimumNumberOfProcessors       :
minimumCpuSpeedInMHz            :
msiInformation                  :
setupFilePath                   : install.cmd
minimumSupportedWindowsRelease  : 1607
displayVersion                  :
minimumSupportedOperatingSystem : @{v8_0=False; v8_1=False; v10_0=False; v10_1607=True; v10_1703=False; v10_1709=False; v10_1803=False; v10_1809=False; v10_1903=False; v10_1909=False; v10_2004=False; v10_2H20=False; v10_21H1=False}
detectionRules                  : {@{@odata.type=#microsoft.graph.win32LobAppFileSystemDetection; path=C:\Program Files\VMware\VMware tools; fileOrFolderName=vmtoolsd.exe; check32BitOn64System=False; detectionType=exists; operator=notConfigured; detectionValue=}}
requirementRules                : {}
rules                           : {@{@odata.type=#microsoft.graph.win32LobAppFileSystemRule; ruleType=detection; path=C:\Program Files\VMware\VMware tools; fileOrFolderName=vmtoolsd.exe; check32BitOn64System=False; operationType=exists; operator=notConfigured; comparisonValue=}}
installExperience               : @{runAsAccount=system; deviceRestartBehavior=suppress}
returnCodes                     : {@{returnCode=0; type=success}, @{returnCode=1707; type=success}, @{returnCode=3010; type=softReboot}, @{returnCode=1641; type=hardReboot}…}

The Rules attribute has more data in it:

@odata.type          : #microsoft.graph.win32LobAppFileSystemRule
ruleType             : detection
path                 : C:\Program Files\VMware\VMware tools
fileOrFolderName     : vmtoolsd.exe
check32BitOn64System : False
operationType        : exists
operator             : notConfigured
comparisonValue      :

You can use access that data in scripts like this:

$JSON.rules.path

Which returns ‘C:\Program Files\VMware\VMware tools’

More advanced information about the ConvertFrom-Json cmdlet can be found here

Writing JSON files in PowerShell

You can also output information to a JSON file using the ConvertTo-Json cmdlet, in the example below I output the data from the Get-Childitem cmdlet to a JSON file (d:\temp\files.json) using ConvertTo-Json and Out-File:

Get-ChildItem | ConvertTo-Json | Out-File d:\temp\files.json

This outputs all file in the current directory to a JSON file:

[
  {
    "Parent": {
      "Parent": "D:\\Temp\\IntuneBackup",
      "Root": "D:\\",
      "FullName": "D:\\Temp\\IntuneBackup\\Client Apps",
      "Extension": "",
      "Name": "Client Apps",
      "Exists": true,
      "CreationTime": "2022-03-31T11:03:14.2325468+02:00",
      "CreationTimeUtc": "2022-03-31T09:03:14.2325468Z",
      "LastAccessTime": "2022-08-09T14:14:31.1320904+02:00",
      "LastAccessTimeUtc": "2022-08-09T12:14:31.1320904Z",
      "LastWriteTime": "2022-03-31T13:25:02.6287275+02:00",
      "LastWriteTimeUtc": "2022-03-31T11:25:02.6287275Z",
      "LinkTarget": null,
      "Attributes": 16
    },
    "Root": {
      "Parent": null,
      "Root": "D:\\",
      "FullName": "D:\\",
      "Extension": "",
      "Name": "D:\\",
      "Exists": true,
      "CreationTime": "2022-01-28T20:12:25.3310114+01:00",
      "CreationTimeUtc": "2022-01-28T19:12:25.3310114Z",
      "LastAccessTime": "2022-08-09T14:14:31.1302723+02:00",
      "LastAccessTimeUtc": "2022-08-09T12:14:31.1302723Z",
      "LastWriteTime": "2022-07-12T22:29:31.1157868+02:00",
      "LastWriteTimeUtc": "2022-07-12T20:29:31.1157868Z",
      "LinkTarget": null,
      "Attributes": 22
    },
    "FullName": "D:\\Temp\\IntuneBackup\\Client Apps\\Assignments",
    "Extension": "",
    "Name": "Assignments",
....................

But… When running the command above, it shows a warning:

WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 2.

In the output above you can see that, the depth value is not high enough to display everything. You can change that but it has a maximum of 100. Running the same command again with a setting of 100 will still show you an error because the output still exceeds that maximum of 100 and it will not show you more detail.

This is something that you will have to take into consideration, limit the things that you want to store in the JSON file before writing to a file.

More advanced information about the ConvertTo-Json cmdlet can be found here.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.