Ask ChatGPT for PowerShell JSON that stays an array with zero or one result

Tell ChatGPT which PowerShell version runs your script and whether the receiving program expects an array, an object or a report envelope. A pipeline that produces no objects, one object or several objects can lead to different JSON shapes. For an always-array report, collect the selected objects into an array and pass that array explicitly to ConvertTo-Json -InputObject.

This matters when today's inventory has one qualifying item. A consumer written to loop over [] should not have to guess whether a single {...} response means the contract changed.

Rehearse with in-memory records

This original exercise reads no files and makes no system changes. Save it as inventory-shape.ps1:

$records = @(
    [pscustomobject]@{ Name = 'North'; Active = $true }
    [pscustomobject]@{ Name = 'South'; Active = $false }
)

$none = @($records | Where-Object { $_.Name -eq 'Missing' })
$one = @($records | Where-Object { $_.Active })
$many = @($records)

Write-Output ('none=' + (ConvertTo-Json -InputObject $none -Depth 3 -Compress))
Write-Output ('one=' + (ConvertTo-Json -InputObject $one -Depth 3 -Compress))
Write-Output ('many=' + (ConvertTo-Json -InputObject $many -Depth 3 -Compress))

The expected shapes are:

none=[]
one=[{"Name":"North","Active":true}]
many=[{"Name":"North","Active":true},{"Name":"South","Active":false}]

This exact example produced array lengths 0, 1 and 2 under Windows PowerShell 5.1 during preparation. Property ordering is not the report's contract. The checks that matter are the top-level array, its length and the record values. @(...) collects pipeline output, including an empty result, while the named InputObject parameter supplies that collected array as the value being serialized.

Microsoft's array guide and ConvertTo-Json reference, checked October 24, 2026, describe these boundaries. PowerShell 7 also documents -AsArray; do not assume that switch exists on an older Windows PowerShell installation. The explicit array-and-InputObject form keeps this exercise clear about the object being supplied.

Check the actual shell before adapting the report

Run $PSVersionTable.PSVersion in the terminal that will execute the script. Use that shell's script invocation, such as pwsh -NoProfile -File ./inventory-shape.ps1 when PowerShell 7 is installed, or run ./inventory-shape.ps1 inside the intended PowerShell session.

When replacing the fictional records with a command, keep collection and serialization separate. Avoid piping through Format-Table first: formatting objects are for display and are not the original inventory records. Select the intended data properties before conversion. For nested data, choose a depth that represents the report and inspect truncation warnings in versions that provide them.

Request a shape contract, then test all three counts

Draft a read-only PowerShell report; do not run system changes.
Actual PowerShell version and permitted input command: [ENTER]
Required properties and nested fields: [ENTER]
Consumer contract: the JSON top-level value is always an array.

Collect selected objects and serialize the collected array explicitly.
Show zero-result, one-result and two-result fixtures. Do not convert
records to display-format objects or wrap JSON in a quoted string.
Choose a justified JSON depth. Keep version-specific alternatives
separate and show expected shapes without inventing actual execution.

The Windows environment guide helps when the wrong shell is launching a command. Once this script runs in the intended shell, parse all three outputs with the receiving program and check array lengths 0, 1 and 2. Keep those fixtures with the report so a later filtering change cannot quietly change the consumer's input type.

Keep reading