Skip to content

Fix Export-Json ignoring -Depth unless -Compact is used #45

Description

Context and request

Observed behavior. Export-Json -Depth is only honoured when -Compact is also supplied. Without -Compact, the parameter has no effect at all.

The compact path serializes with the caller's depth:

$formattedJson = $objectToExport | ConvertTo-Json -Depth $Depth -Compress

The pretty path delegates to Format-Json, which does not accept a depth and hard-codes its own:

$formattedJson = Format-Json -InputObject $objectToExport -IndentationType $IndentationType -IndentationSize $IndentationSize
# Format-Json internally: $inputObject | ConvertTo-Json -Depth 100 -Compress:$Compact

Compounding this, -Depth defaults to 2 while Format-Json uses 100. So the same object exported the same way produces different data depending on a formatting switch.

Reproduced against main:

$deep = [pscustomobject]@{ l1 = [pscustomobject]@{ l2 = [pscustomobject]@{ l3 = [pscustomobject]@{ l4 = 'deep' } } } }
$deep | ConvertTo-Json -Depth 2 -Compress
# {"l1":{"l2":{"l3":"@{l4=deep}"}}}     <- what Export-Json -Compact writes by default

The nested object at level 4 is flattened into the string "@{l4=deep}". The written file is no longer a faithful representation of the input, and the loss is silent.

Expected behavior. -Depth applies identically on both paths, and its default does not silently truncate ordinary nested data.

Reproduction.

$deep = [pscustomobject]@{ l1 = [pscustomobject]@{ l2 = [pscustomobject]@{ l3 = [pscustomobject]@{ l4 = 'deep' } } } }
Export-Json -InputObject $deep -Path ./compact.json -Compact -Force
Export-Json -InputObject $deep -Path ./pretty.json -Force
Get-Content ./compact.json   # truncated at level 3
Get-Content ./pretty.json    # fully preserved

Environment. src/functions/public/Export-Json.ps1 ($Depth default 2, lines 74 and 138) and src/functions/public/Format-Json.ps1 (hard-coded -Depth 100, line 59). Module v1.2.3. Reproduced on PowerShell 7 on Windows; the logic is platform-independent.

Regression. Unknown. Present since Export-Json was introduced as far as the current source shows; no prior working version identified.

Workaround. Always pass an explicit -Depth high enough for the data and avoid -Compact, or serialize with ConvertTo-Json directly and use the -JsonString parameter set.

Acceptance criteria.

  • Export-Json -Depth <n> produces identical nesting depth with and without -Compact.
  • The default depth does not truncate ordinary nested objects.
  • A regression test exports the same object on both paths and asserts the results are structurally equivalent.
  • No warning-free silent truncation remains on either path.

Technical decisions

Verified cause: two independent serialization sites with different depths, and only one of them reachable by the caller's -Depth.

The fix is to give Format-Json a -Depth parameter and have Export-Json pass its value through, so there is one depth applied at one place. Hard-coding 100 in both would remove the inconsistency but also remove the caller's control, which the parameter exists to provide.

The default changes from 2 to something that does not truncate realistic data. Format-Json's existing 100 is the natural choice and is already the effective default on the pretty path — so aligning on it changes behaviour only for -Compact callers who were being truncated, which is the defect being fixed.

Adding -Depth to Format-Json is an additive parameter change and not breaking. Raising Export-Json's default is user-visible in output content and warrants a Minor label.

Not in scope: ConvertTo-Json emits a warning when it truncates; whether the module should surface that is a separate design question.

Implementation plan

  • Add a regression test exporting a 5-level object with and without -Compact and asserting structural equivalence, and confirm it fails
  • Add a -Depth parameter to Format-Json and use it in place of the hard-coded 100
  • Pass -Depth from Export-Json through to Format-Json on the pretty path
  • Raise Export-Json's -Depth default so ordinary nested data is not truncated
  • Add a test asserting an explicit -Depth truncates identically on both paths
  • Update the comment-based help for both commands to describe the depth behaviour
  • Confirm the existing suite still passes and coverage holds at the 95% target
  • Apply the Minor label

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions