Though there are many file formats used for configuration and data storage. JSON, or JavaScript Object Notation, files have become very common. They offer an easy to understand and compact format to define information. In addition, they integrate exceptionally well within PowerShell. One of its powerful functions is the PowerShell import JSON, allowing JSON data to be imported as pipelinable objects that can be subsequently exported.
What’s changed in PowerShell 7 to enhance support for JSON? There are no new cmdlets, but there have been some functionality changes to the existing cmdlets.
Before diving into the new functionality, how does PowerShell work with JSON? Let’s walk through a few examples. We will explore how to import JSON, manipulate an object, and export the JSON to a file that can be later consumed.
First, we want to consume a JSON file and then update the values for later use. This type of technique is often used when storing information about a given system, for example, the computer name, environmental properties, etc. In this example, we are going to use a simple JSON file.
computer.json
{
"SystemName": "TestSystem",
"LastBoot": "3/28/2020 11:27:15 AM",
"User": "TestUser",
"LoggedOn": true
}
By retrieving the content of the JSON file and then converting that content from JSON, a standard PowerShell object is output.
Get-Content -Path "D:computer.json" | ConvertFrom-JSON
How is the object actually seen by PowerShell? When the JSON is imported, PowerShell converts the data into a PSCustomObject and attempts to match the properties into their types, such as string or bool types. The strength of PowerShell import JSON lies in this seamless conversion process.
Similar to importing JSON, we are able to export a PowerShell object that has been modified or changed. Adding to our above example, what if we want to add a property to our existing imported JSON, such as the PowerShell version. After we save our imported content to a variable, we can then add on a new property.
$JSON = Get-Content -Path "D:computer.json" | ConvertFrom-JSON
$JSON | Add-Member -Name "PSVersion" -MemberType NoteProperty -Value "7.0"
Now that we have added the new property to our object, let’s export this object and overwrite our existing JSON file, showcasing the full circle PowerShell import JSON process along with export functionalities.
$JSON | ConvertTo-JSON | Out-File "D:computer.json"
As you can tell, the new property PSVersion has been added and can be appropriately updated as necessary.
In any script or function, it is crucial to test the input and output to make sure that the data is not corrupted or that it will cause further issues down the line. Thankfully, PowerShell added Test-JSON in version 6.x. We have two options, pass in a file as a string that Test-JSON can operate on, or a pass a string from the command-line itself.
Get-Content -Path "D:computer.json" -Raw | Test-JSON
Note that Get-Content is using the Raw parameter. This returns the file content as one single string instead of an array of strings which Test-JSON cannot process.
What if we want to send in just a simple JSON string to make sure that it’s valid before we save the data? Thankfully, this is also very simple to do with Test-JSON.
'{
"SystemName": "TestSystem",
"LastBoot": "3/28/2020 11:27:15 AM",
"User": "TestUser",
"LoggedOn": true,
"PSVersion": "7.0"
}' | Test-JSON
Now that you know how to work with JSON in PowerShell, what does version 7 bring to the table to help enhance support for JSON data? There are a few new parameters available for ConvertTo-JSON and ConvertFrom-JSON that will help with edge cases and the transformation of JSON data.
There are two new parameters available as seen below.
EnumsAsStringsAsArrayEnumsAsStrings
Although not typically used as much in PowerShell, an enum is a structured data type that enables a variable to be a set of predefined constants. When referencing an enum, the resulting value is a zero-based index. When outputting an enum value from PowerShell to JSON, the numerical value itself would be output, which isn’t always ideal. Often, the string name of the enum would be preferable.
Without the EnumsAsStrings parameter defined, we can see just the values being output.
With the EnumsAsStrings parameter, the correct string names are shown.
AsArray
Similar to how the EnumsAsStrings works, AsArray will wrap pipeline input as an array whether or not it is a single item or multiple items.
Just like ConvertTo-JSON, ConvertFrom-JSON has added a new parameter and changed some functionality.
NoEnumerateNoEnumerate
Prior to PowerShell 7 the default behavior of ConvertFrom-JSON was to not unwrap collections by default. This meant that if a JSON array was passed into PowerShell it would be seen as a single object and not as multiple objects.
# PowerShell 5.1
PS> ('["first","second","third"]' | ConvertFrom-JSON | Measure-Object).Count
1
In PowerShell 7, the new behavior is to unwrap collections which is much more in line with how most cmdlets and functions work within PowerShell.
By using the NoEnumerate property, this will change the default behavior back to the original method used prior to PowerShell 7.
Changed Depth Behavior
One final note on ConvertFrom-JSON, the Depth parameter now allows much larger values than it did prior to PowerShell 7. Starting in PowerShell 7, the depth now has a default of 1024 but allows up to [Int]::MaxValue which is a vast difference from the 101 limit that older versions of PowerShell had.
Using and manipulating JSON content in PowerShell is easy to do and offers any number of ways to transform the data to meet your exact needs. Many of the additions that have been added in recent years are community requested additions to make working with JSON that much easier. PowerShell 7 has continued that tradition and expanded even further on the usefulness of the built-in PowerShell JSON functionality.
You can verify a successful PowerShell import JSON operation by using try-catch blocks, checking the object properties with Get-Member, or utilizing the $? automatic variable which indicates the success status of the last operation. Additionally, you can pipe the imported JSON to Select-Object to ensure all expected properties are present.
When performing PowerShell import JSON operations on large files, consider using StreamReader instead of Get-Content, implement pagination if possible, use -Raw parameter for better memory management, and utilize PowerShell jobs for parallel processing of multiple JSON files.
Yes, you can merge multiple JSON files by using PowerShell import JSON operations in a loop, combining the objects with Add-Member or the += operator, and then creating a new consolidated JSON file. This is particularly useful for configuration management and data consolidation tasks.
To handle special characters in PowerShell import JSON operations, use UTF8 encoding with -Encoding parameter, escape special characters properly, and consider using the [System.Web.HttpUtility]::HtmlDecode() method for HTML-encoded content within your JSON files.
Implement comprehensive error handling for PowerShell import JSON operations by using try-catch blocks with specific error types, validating JSON schema before import, implementing logging mechanisms, and using the -ErrorAction parameter to control how PowerShell handles errors during import operations.