Last Update: Sep 04, 2024 | Published: Mar 31, 2020
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. Functionality such as the ability 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.
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.
$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.
EnumsAsStrings
AsArray
EnumsAsStrings
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.
NoEnumerate
NoEnumerate
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.