Real scripts read data from files and APIs, reshape it and write reports.
[pscustomobject]@{ Name = 'web1'; CPU = 72 } creates an object with those properties, in that order. Custom objects flow through the pipeline like any cmdlet output: you can filter, sort, group and export them. They are the right way to return structured results from your functions, instead of formatted strings.
JSON: ConvertTo-Json serializes objects (mind -Depth: the default of 2 truncates deeper nesting, with a warning), and ConvertFrom-Json parses text into objects; -AsHashtable gives hashtables instead. Read a file with Get-Content file.json -Raw | ConvertFrom-Json.
CSV: Export-Csv writes objects (PowerShell 7 no longer adds a type header, so -NoTypeInformation is optional), and Import-Csv reads rows back as objects whose property values are all strings. Cast before comparing numbers: [int]$_.CPU -gt 50.
REST: Invoke-RestMethod calls an HTTP API and converts the JSON response into objects automatically; Invoke-WebRequest gives the raw response with status code and headers.
To add a property to an existing object use Add-Member or Select-Object *, @{ Name = 'New'; Expression = { ... } }. ForEach-Object Name (member name shorthand) pulls a single property out of each object.
Example
Set-Location ([IO.Path]::GetTempPath())
$servers = @(
[pscustomobject]@{ Name = 'web1'; CPU = 72; Env = 'prod' }
[pscustomobject]@{ Name = 'web2'; CPU = 15; Env = 'prod' }
[pscustomobject]@{ Name = 'dev1'; CPU = 90; Env = 'dev' }
)
$servers | Where-Object CPU -gt 50 | ForEach-Object Name # web1 / dev1
$json = $servers | ConvertTo-Json -Compress
$json.Substring(0, 38) # [{"Name":"web1","CPU":72,"Env":"prod"}
$back = $json | ConvertFrom-Json
$back[2].CPU + 1 # 91
$servers | Export-Csv servers.csv
(Import-Csv servers.csv)[0].CPU.GetType().Name # String (CSV is text)
@(Import-Csv servers.csv | Where-Object { [int]$_.CPU -gt 50 }).Count # 2
$servers | Group-Object Env | ForEach-Object { "$($_.Name): $($_.Count)" } # dev: 1 / prod: 2 (groups sorted by name)
# $repo = Invoke-RestMethod https://api.github.com/repos/PowerShell/PowerShell
# $repo.stargazers_count # JSON response arrives as objectsRemember
- [pscustomobject]@{ } is the standard record type
- ConvertTo-Json needs -Depth for nested data
- Import-Csv values are strings; cast before numeric comparisons
Watch out for
- Comparing Import-Csv values as numbers without casting: '9' -gt '50' is True as strings.