Skip to content

Align Json's function structure and error semantics with the standard #42

Description

Context and request

The three public commands diverge from the MSX PowerShell function standard in ways that affect how callers use and debug them.

Format-Json uses return $json to emit its result, where the standard requires emitting implicitly. More seriously, it wraps its body in try/catch and ends the catch with Write-Error "Failed to format JSON: $_" without rethrowing, so malformed input produces a non-terminating error and $null on the success stream. A caller that does not check $ErrorActionPreference silently receives nothing.

Export-Json carries an empty begin {} block.

Both multi-set commands name their parameter sets FromString and FromObject. The standard asks for prose phrases that read naturally in Get-Help syntax output, since those names appear verbatim to anyone calling the command.

Acceptance criteria.

  • Malformed input to Format-Json produces a terminating error that try/catch around the call can trap.
  • No function uses return to emit its result.
  • The empty begin {} block is gone.
  • Get-Help <Command> shows parameter set names that read as scenarios rather than internal identifiers.
  • Existing tests pass unchanged, including Should throw error on invalid input.
  • Behaviour for valid input is byte-identical to the current implementation.

Technical decisions

Renaming the parameter sets is not a breaking change. Sets are selected by which parameter the caller supplies, and no caller passes a set name; only Get-Help output changes. Suggested names: 'From JSON string' and 'From object'. DefaultParameterSetName on [CmdletBinding()] is updated to match.

Changing Format-Json to fail terminally is observable. Callers who currently receive $null from malformed input will start seeing an exception. This is the behaviour the standard requires — throw for terminating errors, Write-Error only where the caller is expected to handle a non-terminating one — and the existing test already asserts Should -Throw, which passes today only because Write-Error throws under the test harness's ErrorActionPreference. Making it explicit removes that dependency on ambient configuration. This warrants a Minor label.

Export-Json's catch blocks are reviewed at the same time. It catches ArgumentException, DirectoryNotFoundException, and UnauthorizedAccessException and converts each to Write-Error, and the general catch references $resolvedPath, which is unassigned if the failure occurred before that line — producing a confusing message. The standard's guidance to copy $_ into a local variable before later commands overwrite it applies here.

No <Group> folders are introduced. PSModule/Hashtable and PSModule/Uri, the reference data modules, both keep a flat src/functions/public/, and a single-domain module gains nothing from a group level.

This ships separately from the output-contract change so the observable error-semantics change is reviewable on its own.

Implementation plan

  • Add a test asserting that Format-Json with malformed input throws a terminating error catchable by try/catch, and confirm it fails first
  • Rethrow rather than swallow in Format-Json's catch block
  • Replace return $json and return ($result -join "\n")` with implicit emission
  • Rename the parameter sets to prose phrases in both Format-Json and Export-Json, updating DefaultParameterSetName
  • Remove the empty begin {} block from Export-Json
  • Review Export-Json's catch blocks: copy $_ locally and stop referencing possibly-unassigned $resolvedPath
  • Confirm output for valid input is unchanged against the existing suite
  • Confirm Get-Help syntax output reads naturally for both multi-set commands
  • Apply the Minor label for the error-semantics change

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