Skip to content
shellmap

convertto-jsonSerialise PowerShell objects to JSON strings across all 5 shells

Equivalents in every shell

Bashunix
jq -n --arg name alice '{name: $name}'

`jq -n` (null input) is the canonical way to build a JSON object from shell variables — `--arg key value` for strings, `--argjson key value` for numbers / objects / arrays parsed as JSON. For an array of objects, switch to a heredoc + `jq -s` or generate inline via `printf` and pipe through `jq .`.

Zshunix
jq -n --arg name alice '{name: $name}'

Same external `jq`. macOS has no jq in base — install via `brew install jq`. Zsh's `print -r --` is useful when feeding multi-line literal JSON into `jq` without backslash-escaping every internal quote.

Fishunix
jq -n --arg name alice '{name: $name}'

Same external `jq`. Fish's string-quoting story is simpler — `jq -n --arg name "$value" '{name: $name}'` works even when `$value` contains spaces or special characters without any escape gymnastics.

PowerShellwindows
@{name='alice'} | ConvertTo-Json

Takes any object or hashtable on the pipeline (or via `-InputObject`) and emits a pretty-printed JSON string. Aliases: none. Numbers, strings, booleans, `$null`, dates (as ISO 8601), and nested hashtables / arrays all serialise correctly. Use `-Compress` for one-line output.

cmd.exewindows
powershell -NoProfile -Command "@{name='alice'} | ConvertTo-Json -Compress"

cmd.exe has no native object model. Shell out to PowerShell via `powershell -NoProfile -Command` (skips $PROFILE for faster startup) and rely on its `ConvertTo-Json`. For pure-cmd JSON construction, the only realistic option is `echo {"name":"alice"}` with manual quote-escaping — error-prone past one field.

Worked examples

Build a nested JSON object from a hashtable

Bash
jq -n --arg name alice --argjson age 30 '{user: {name: $name, age: $age}}'
PowerShell
@{user=@{name='alice'; age=30}} | ConvertTo-Json

Serialise an array of objects (deep tree) and stream to disk

Bash
jq -n '[{id:1, tags:["a","b"]}, {id:2, tags:["c"]}]' > out.json
PowerShell
@(@{id=1; tags=@('a','b')}, @{id=2; tags=@('c')}) | ConvertTo-Json -Depth 10 | Out-File out.json -Encoding utf8

Emit compact one-line JSON for HTTP body payloads

Bash
jq -nc --arg name alice '{name: $name}'
PowerShell
@{name='alice'} | ConvertTo-Json -Compress

Gotchas

  • **The #1 footgun**: `ConvertTo-Json` defaults to `-Depth 2` and SILENTLY TRUNCATES anything deeper — your nested objects become string representations like `"System.Collections.Hashtable"`. Always pass `-Depth 10` (or higher) for non-trivial graphs. pwsh 7.3+ warns on truncation; 5.1 + early 7.x stays silent.
  • Dates serialise as ISO 8601 strings (`2026-05-16T07:30:00`) WITHOUT timezone offset — the local kind is dropped. To preserve timezone, use `[DateTimeOffset]::Now.ToString("o")` explicitly before serialising. For Unix timestamps, convert to `[DateTimeOffset]::UtcNow.ToUnixTimeSeconds()` first.
  • `$null` serialises to JSON `null` (correct), but UNDEFINED PROPERTIES on a `[PSCustomObject]` are silently OMITTED from the output — different from JavaScript `JSON.stringify` which preserves them as `null`. To force-include, set them explicitly: `$obj.foo = $null`.
  • Hashtable key ORDER is not preserved on `[hashtable]` (it's an unordered map). Use `[ordered]@{a=1; b=2}` to force insertion order in the output JSON. pwsh 5.1 always reorders; 7+ is more stable but still not guaranteed.
  • Enums serialise as their NUMERIC value (`0`, `1`, …) not their name string. To get the readable name, cast `.ToString()` before piping. PSCustomObjects with `[Flags]` enums round-trip lossily.

WSL & PowerShell Core notes

pwsh`ConvertTo-Json` is identical across Windows / Linux / macOS pwsh — same serialiser (`System.Text.Json` since pwsh 7.4, Newtonsoft.Json before). The `-Depth` default and silent-truncation behaviour are also identical, so portable scripts must always specify `-Depth` explicitly.
WSLFrom WSL bash, `pwsh.exe -c "@{name='alice'} | ConvertTo-Json"` invokes the Windows-side serialiser — useful when interoperating with Windows-side scripts that consume the output. Pure-WSL workflows stick to `jq -n` for shell-variable-to-JSON construction.

Common tasks using convertto-json

Related commands