Skip to content

Add Import-Yaml and Export-Yaml file I/O functions #29

@MariusStorhaug

Description

Scripts and automation that work with YAML configuration files currently require a two-step pattern to read or write YAML:

# Reading
$config = Get-Content config.yaml -Raw | ConvertFrom-Yaml

# Writing
$config | ConvertTo-Yaml | Set-Content config.yaml

Every other PowerShell serialization format ships a Convert* pair and an Import- / Export- pair for direct file I/O: Import-Csv / Export-Csv, Import-Clixml / Export-Clixml. Users expect the same convenience for YAML.

Request

Desired capability

An Import-Yaml function that reads a YAML file and returns a PowerShell object, and an Export-Yaml function that serializes a PowerShell object directly to a YAML file. Both functions should delegate serialization logic to the existing ConvertFrom-Yaml and ConvertTo-Yaml functions, adding only the file I/O layer and the standard parameters that PowerShell file cmdlets provide.

Import-Yaml reads a file and returns an object — the file-based counterpart of ConvertFrom-Yaml:

$config = Import-Yaml -Path config.yaml
$config = Import-Yaml -Path config.yaml -AsHashtable

Export-Yaml writes an object to a file — the file-based counterpart of ConvertTo-Yaml:

$config | Export-Yaml -Path config.yaml
$config | Export-Yaml -Path config.yaml -NoClobber

Standard PowerShell Import/Export parameters

The following parameters are shared across all built-in Import-* / Export-* cmdlets and should be present on the YAML equivalents:

Parameter Import-Yaml Export-Yaml Description
-Path File path (position 0, wildcards allowed on import)
-LiteralPath Literal file path (no wildcard expansion)
-Encoding File encoding (default: utf8NoBOM, consistent with PowerShell 7+)
-InputObject Object to export (ValueFromPipeline)
-NoClobber Fail if the output file already exists
-Force Overwrite read-only files
-Append Append to existing file instead of overwriting

YAML-specific parameters (passthrough from Convert functions)

Parameter Import-Yaml Export-Yaml Source
-AsHashtable ConvertFrom-Yaml
-NoEnumerate ConvertFrom-Yaml
-Depth Both
-EnumsAsStrings ConvertTo-Yaml
-AsArray ConvertTo-Yaml
-Indent ConvertTo-Yaml

Pipeline behavior

Consistent with the established PowerShell pattern:

  • Import-Yaml-Path accepts [string[]] and pipeline input by property name. Returns [PSCustomObject] or [OrderedDictionary] per file.
  • Export-Yaml-InputObject accepts pipeline input. Writes to the file and returns nothing (void), consistent with Export-Csv. Buffers all pipeline input before writing (same as ConvertTo-Yaml).

Aliases

Import-Yml for Import-Yaml, Export-Yml for Export-Yaml — matching the existing ConvertFrom-Yml / ConvertTo-Yml alias pattern.

Acceptance criteria

  • Import-Yaml -Path file.yaml returns the same object as Get-Content file.yaml -Raw | ConvertFrom-Yaml
  • $obj | Export-Yaml -Path file.yaml produces the same file content as $obj | ConvertTo-Yaml | Set-Content file.yaml
  • -NoClobber prevents overwriting an existing file
  • -Force overwrites read-only files
  • -Append appends serialized YAML to an existing file (with a document separator --- between entries)
  • -Encoding controls file encoding (default utf8NoBOM)
  • -LiteralPath works with paths containing wildcard characters
  • All YAML-specific parameters pass through to the underlying Convert functions
  • Pipeline input works for both functions
  • ShouldProcess support (-WhatIf, -Confirm) on Export-Yaml

Technical decisions

Architecture: Thin wrappers around ConvertFrom-Yaml and ConvertTo-Yaml. The Import/Export functions handle only file I/O, encoding, and the standard file-cmdlet parameters. All YAML parsing and serialization logic stays in the Convert functions.

Function placement: src/functions/public/Import-Yaml.ps1 and src/functions/public/Export-Yaml.ps1, following the existing one-file-per-function convention.

Parameter sets: Two parameter sets on each function — Path (default, position 0) and LiteralPath — matching the Import-Csv / Export-Csv pattern. Path and LiteralPath are mutually exclusive via parameter sets.

Encoding type: Use [System.Text.Encoding] with a default of [System.Text.Encoding]::UTF8 (BOM-less UTF-8), consistent with PowerShell 7+ defaults. Accept the same string shortcuts that Set-Content / Get-Content accept.

Append behavior: When -Append is used on Export-Yaml, prepend a --- document separator before the new content. This produces a valid multi-document YAML stream. Note: Import-Yaml does not yet support multi-document streams (#21) — appended content can be read back one document at a time once #21 lands.

ShouldProcess: Export-Yaml supports [CmdletBinding(ShouldProcess)] for -WhatIf and -Confirm, consistent with Export-Csv.

File reading: Use Get-Content -Raw internally for Import, Set-Content / Add-Content for Export. This keeps encoding handling consistent with PowerShell conventions and avoids reimplementing file I/O.

Breaking changes: None. New functions only — existing ConvertFrom-Yaml and ConvertTo-Yaml are unchanged.

Test approach: Pester tests using TestDrive: for file system isolation. Test matrix: basic round-trip via file, -NoClobber, -Force, -Append, -Encoding, -LiteralPath with bracket characters, -AsHashtable passthrough, pipeline input, -WhatIf.


Implementation plan

Core functions

  • Add Import-Yaml in src/functions/public/Import-Yaml.ps1 with Import-Yml alias
  • Add Export-Yaml in src/functions/public/Export-Yaml.ps1 with Export-Yml alias

Tests

  • Add tests/Import-Yaml.Tests.ps1 — basic file read, -AsHashtable, -NoEnumerate, -Encoding, -LiteralPath, pipeline of paths, missing file error
  • Add tests/Export-Yaml.Tests.ps1 — basic file write, -NoClobber, -Force, -Append with --- separator, -Encoding, -LiteralPath, -WhatIf, pipeline input, round-trip via Import-Yaml
  • Add round-trip test: $obj | Export-Yaml -Path $f; Import-Yaml -Path $f produces equivalent object

Documentation

  • Update examples/General.ps1 with Import/Export usage examples
  • Update function help (comment-based help in each .ps1 file)

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions