Skip to content
AgileLogics
5 min read

Working with JSON

Prerequisites: Custom objects, Hash tables

ConvertFrom-Json turns JSON text into objects; ConvertTo-Json turns objects into JSON.

$json = @'
{
  "name": "web01",
  "ports": [80, 443],
  "owner": { "team": "platform", "email": "ops@example.com" }
}
'@

$config = $json | ConvertFrom-Json
$config.name
$config.ports -join ', '
$config.owner.team
web01
80, 443
platform

Nested objects and arrays become nested properties — navigate with dots.

Creating JSON

$report = [ordered]@{
  generated = '2025-04-22'
  servers   = @(
    @{ name = 'web01'; healthy = $true }
    @{ name = 'db01';  healthy = $false }
  )
}
$report | ConvertTo-Json
{
  "generated": "2025-04-22",
  "servers": [
    {
      "healthy": true,
      "name": "web01"
    },
    {
      "healthy": false,
      "name": "db01"
    }
  ]
}

The -Depth trap

ConvertTo-Json only goes 2 levels deep by default. Deeper data is flattened to text, with a warning:

$deep = @{ a = @{ b = @{ c = @{ d = 'value' } } } }
$deep | ConvertTo-Json -Compress
$deep | ConvertTo-Json -Compress -Depth 10
WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 2.
{"a":{"b":{"c":"System.Collections.Hashtable"}}}
{"a":{"b":{"c":{"d":"value"}}}}

Always pass -Depth for nested data (the maximum is 100). -Compress removes whitespace.

Files and editing

Set-Content settings.json '{ "theme": "light", "fontSize": 14 }'

$settings = Get-Content settings.json -Raw | ConvertFrom-Json
$settings.theme = 'dark'
$settings | Add-Member -NotePropertyName autosave -NotePropertyValue $true
$settings | ConvertTo-Json -Compress | Set-Content settings.json

Get-Content settings.json
{"theme":"dark","fontSize":14,"autosave":true}

Use -Raw when reading, so the whole file is parsed as one document. ConvertFrom-Json -AsHashtable returns hash tables instead, useful when keys aren't valid property names. Check or pretty-print JSON with the JSON Formatter.