Master PowerShell JSON Conversion: ConvertFrom-Json & ConvertTo-Json
Learn how PowerShell’s ConvertFrom-Json and ConvertTo-Json cmdlets turn JSON into objects and back, covering depth, type conversion, performance, and security. Practical examples and a checklist help you use them safely in production scripts.
17 May 2026, 23:14 UTC

Problem: Turning JSON into PowerShell objects (and back) without losing data or blowing up
When writing scripts that call REST APIs, read configuration files, or generate JSON for downstream tools, you quickly run into the need to move fluidly between a JSON string and a PowerShell object model. The built‑in ConvertFrom-Json and ConvertTo-Json cmdlets handle this, but they have quirks that can trip up even seasoned scripters. This post walks through the practical details you need to make a confident decision about how to use them in production scripts.
Thesis: Use the depth‑aware, type‑preserving conversion pipeline, but always guard against untrusted input and large payloads.
PowerShell 7+ makes JSON handling straightforward, yet you still need to tune -Depth, understand automatic type conversion, and be aware of security implications. By following the guidelines below you can avoid common pitfalls and keep scripts maintainable.
1. Converting JSON to objects – ConvertFrom-Json
At its core, ConvertFrom-Json reads a JSON string and produces a nested hierarchy of PSObject/PSCustomObject instances. Nested arrays become System.Collections.ArrayList objects, and nested objects become PSCustomObject instances. The cmdlet also performs .NET type conversion for certain scalar values.
Example: Reading a configuration file
# Load the entire file as a single string
$configJson = Get-Content -Path 'config.json' -Raw
# Convert to a PowerShell object
$config = $configJson | ConvertFrom-Json
# Inspect the top‑level properties
$config | Get-Member | Format-Table Name, MemberType, Definition
Notice how the -Raw switch is crucial; without it Get-Content would return an array of lines, which ConvertFrom-Json would then try to parse line‑by‑line, producing a malformed object.
Depth Matters
JSON can nest arbitrarily deep. The default depth in PowerShell 7 is 100, which covers most use cases but can still trigger a stack overflow if you hit the limit. Specify -Depth explicitly to avoid surprises:
$deepJson = '{"a":{"b":{"c":"value"}}}'
# Default depth will succeed, but if you have >100 levels you need to bump it
$deepObj = $deepJson | ConvertFrom-Json -Depth 200
When you set -Depth too low, you’ll see a ConvertFrom-Json: The JSON string does not contain a valid JSON object. error. A good rule of thumb is to set it a few levels higher than the deepest nesting you expect.
Automatic Type Conversion
PowerShell automatically turns ISO‑8601 strings into System.DateTime objects and GUID strings into System.Guid objects. This is handy for date‑based logic:
$json = '{"created":"2026-10-15T00:00:00Z", "id":"123e4567-e89b-12d3-a456-426614174000"}'
$obj = $json | ConvertFrom-Json
Write-Host $obj.created.GetType().FullName # System.DateTime
Write-Host $obj.id.GetType().FullName # System.Guid
2. Serializing objects back to JSON – ConvertTo-Json
When you modify an object and need to send it back out, ConvertTo-Json turns it into a JSON string. It respects the same -Depth parameter and adds a -Compress flag to remove whitespace for compact output.
Example: Updating a property and sending the result
# Assume $config from earlier
$config.database.port = 5432
# Serialize back to JSON
$payload = $config | ConvertTo-Json -Depth 10 -Compress
# Send via Invoke-RestMethod
Invoke-RestMethod -Uri 'https://api.example.com/config' -Method Put -Body $payload -ContentType 'application/json'
The -Compress flag reduces the size of the payload, which can be critical when the API has a request body limit.
Preserving Order
PowerShell 7+ preserves property order during conversion, whereas PowerShell 5.1 does not. If you need deterministic ordering (e.g., for diffing configuration files), always target 7+ or sort the properties manually before serialization.
3. Performance & Memory Footprint
Both cmdlets create an in‑memory object graph. For files under 10 MB this is usually fine, but larger payloads can consume significant memory and slow down your script. A quick benchmark:
# 50 MB JSON file
$size = 50
$largeJson = '{"data":[' + (1..$size | ForEach-Object { '{"i":$_}' }) + ']}'
$time = Measure-Command { $obj = $largeJson | ConvertFrom-Json }
Write-Host "Deserialization time: $($time.TotalMilliseconds) ms"
If you hit performance constraints, consider streaming approaches: use Get-Content -ReadCount 1 and process line‑by‑line, or switch to a third‑party JSON parser that supports streaming.
4. Security Considerations
In older PowerShell versions (5.1 and earlier) the JSON parser honored a special __type property, allowing malicious payloads to instantiate arbitrary .NET types. PowerShell 7+ ignores this property unless you explicitly enable it with -AsHashtable or -Depth > 0. Still, you should never deserialize untrusted data without validation.
$malicious = '{"__type":"System.Windows.Forms.MessageBox","Message":"Hi"}'
$obj = $malicious | ConvertFrom-Json
Write-Host $obj.GetType().FullName # PSCustomObject – no side effects
Best practice: validate the structure of incoming JSON before converting. For example, use a JSON schema validator or simple property checks.
5. Trade‑offs and Limitations
- Depth vs. Stack Overflow: Too low a depth cuts off data; too high risks stack overflow on very deep JSON.
- Type Conversion Limits: Custom .NET types are serialized as empty objects unless you provide a
ToString()implementation. - Performance: Large payloads can cause memory pressure; consider streaming or third‑party libraries for >10 MB.
- Security: Always validate input; avoid deserializing data from untrusted sources without checks.
Actionable Checklist for Production Scripts
- Use
-RawwithGet-Contentto avoid line‑by‑line parsing. - Explicitly set
-Depthto at least one level higher than your deepest nested object. - Validate the JSON structure before converting (e.g., required properties, type checks).
- When sending data, use
-Compressunless pretty‑printed output is required. - For large payloads, measure memory usage and consider streaming or a dedicated JSON library.
- Keep PowerShell 7+ to benefit from order preservation and improved security defaults.
Conclusion
PowerShell’s ConvertFrom-Json and ConvertTo-Json are powerful tools for integrating JSON into your automation workflows. By understanding depth handling, type conversion, performance limits, and security nuances, you can build robust scripts that reliably transform data between formats. Apply the checklist above to ensure your scripts stay maintainable, performant, and safe.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.