Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ outputs/*
bin/
obj/
libs/

# Test files
test-*.json
84 changes: 84 additions & 0 deletions examples/General.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,88 @@ Remove-Item -Path $configFile, $userFile, $settingsFile -ErrorAction SilentlyCon

#endregion

#region Export-Json Examples

# Example 14: Export simple object to file
'Example 14: Export simple object to file'
$userObject = @{
name = 'John Doe'
age = 30
email = 'john.doe@example.com'
active = $true
roles = @('user', 'contributor')
}

$outputFile = '/tmp/user-export.json'
Export-Json -InputObject $userObject -Path $outputFile -IndentationType Spaces -IndentationSize 2
'Exported to file:'
Get-Content $outputFile

# Example 15: Export with compact formatting
'Example 15: Export with compact formatting'
$compactFile = '/tmp/user-compact.json'
Export-Json -InputObject $userObject -Path $compactFile -Compact
'Compact export:'
Get-Content $compactFile

# Example 16: Export multiple objects via pipeline to same file (last overwrites previous)
'Example 16: Export multiple objects via pipeline'
$users = @(
@{ id = 1; name = 'Alice'; department = 'Engineering' },
@{ id = 2; name = 'Bob'; department = 'Marketing' },
@{ id = 3; name = 'Carol'; department = 'Sales' }
)

$users | Export-Json -Path '/tmp/users-pipeline.json' -IndentationType Tabs -IndentationSize 1
'Pipeline export result (last object only):'
Get-Content '/tmp/users-pipeline.json'

# Example 17: Export JSON string to file
'Example 17: Export JSON string to file'
$jsonString = '{"service":"api","version":"1.2.3","endpoints":["/users","/products","/orders"]}'
$serviceFile = '/tmp/service-config.json'
Export-Json -JsonString $jsonString -Path $serviceFile -IndentationType Spaces -IndentationSize 4
'Formatted JSON string export:'
Get-Content $serviceFile

# Example 18: Roundtrip example - Import, modify, export
'Example 18: Roundtrip example - Import, modify, export'
# First create a JSON file to import
$originalConfig = @{
database = @{
host = 'localhost'
port = 5432
name = 'myapp'
}
features = @{
logging = $true
caching = $false
analytics = $true
}
}

$configFile = '/tmp/original-config.json'
Export-Json -InputObject $originalConfig -Path $configFile

# Import and modify
$config = Import-Json -Path $configFile
$config.database.host = 'production-db.example.com'
$config.features.caching = $true
$config.lastModified = Get-Date -Format 'yyyy-MM-ddTHH:mm:ss'

# Export the modified configuration
$modifiedFile = '/tmp/modified-config.json'
Export-Json -InputObject $config -Path $modifiedFile -IndentationType Spaces -IndentationSize 2

'Original config:'
Get-Content $configFile
''
'Modified config:'
Get-Content $modifiedFile

# Cleanup temporary files
Remove-Item -Path $outputFile, $compactFile, $serviceFile, $configFile, $modifiedFile, '/tmp/users-pipeline.json' -ErrorAction SilentlyContinue

#endregion

"`nAll examples completed!"
170 changes: 170 additions & 0 deletions src/functions/public/Export-Json.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
function Export-Json {
<#
.SYNOPSIS
Exports JSON data to a file.

.DESCRIPTION
Converts PowerShell objects to JSON format and writes them to one or more files.
Supports various formatting options including indentation types, sizes, and compact output.
Can accept both PowerShell objects and JSON strings as input.

.EXAMPLE
Export-Json -InputObject $myObject -Path 'output.json'

Exports a PowerShell object to output.json with default formatting.

.EXAMPLE
Export-Json -InputObject $data -Path 'config.json' -IndentationType Spaces -IndentationSize 2

Exports data to config.json with 2-space indentation.

.EXAMPLE
Export-Json -JsonString $jsonText -Path 'data.json' -Compact

Exports a JSON string to data.json in compact format.

.EXAMPLE
$objects | Export-Json -Path 'output.json'

Exports multiple objects to the same file via pipeline (last object overwrites).

.EXAMPLE
Export-Json -InputObject $config -Path 'settings.json' -IndentationType Tabs -Force

Exports configuration to settings.json with tab indentation, overwriting if it exists.

.LINK
https://psmodule.io/Json/Functions/Export-Json/
#>

[CmdletBinding(DefaultParameterSetName = 'FromObject', SupportsShouldProcess)]
param (
# PowerShell object to convert and export as JSON.
[Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FromObject')]
[PSObject]$InputObject,

# JSON string to export to file.
[Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'FromString')]
[string]$JsonString,

# The path to the output JSON file.
[Parameter(Mandatory)]
[string]$Path,

# Produce compact (minified) output.
[Parameter()]
[switch]$Compact,

# Indentation type: 'Spaces' or 'Tabs'.
[Parameter()]
[ValidateSet('Spaces', 'Tabs')]
[string]$IndentationType = 'Spaces',

# Number of spaces or tabs per indentation level. Only used if not compacting.
[Parameter()]
[UInt16]$IndentationSize = 2,

# The maximum depth to serialize nested objects.
[Parameter()]
[int]$Depth = 2,

# Overwrite existing files without prompting.
[Parameter()]
[switch]$Force,

# Text encoding for the output file.
[Parameter()]
[ValidateSet('ASCII', 'BigEndianUnicode', 'BigEndianUTF32', 'OEM', 'Unicode', 'UTF7', 'UTF8', 'UTF8BOM', 'UTF8NoBOM', 'UTF32')]
[string]$Encoding = 'UTF8NoBOM'
)

begin {
}

process {
try {
# Determine the input object
$objectToExport = if ($PSCmdlet.ParameterSetName -eq 'FromString') {
$JsonString | ConvertFrom-Json -Depth $Depth -ErrorAction Stop
} else {
$InputObject
}

# Generate the file path
$outputPath = $Path

# Resolve the path for consistent operations and error messages
if (Test-Path -Path $outputPath) {
$resolvedPath = Resolve-Path -Path $outputPath
} else {
# For non-existing files, resolve the parent directory and combine with filename
$parentPath = Split-Path -Path $outputPath -Parent
$fileName = Split-Path -Path $outputPath -Leaf
if ($parentPath -and (Test-Path -Path $parentPath)) {
$resolvedParent = Resolve-Path -Path $parentPath
$resolvedPath = Join-Path -Path $resolvedParent -ChildPath $fileName
} else {
# If parent doesn't exist either, use the original path as-is for error messages
$resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($outputPath)
}
}

# Check if file exists and handle accordingly
if ((Test-Path -Path $resolvedPath -PathType Leaf) -and -not $Force) {
if ($PSCmdlet.ShouldProcess($resolvedPath, "Overwrite existing file")) {
# Continue with export
} else {
# Only error if not WhatIf - WhatIf should just show what would happen
if (-not $WhatIfPreference) {
Write-Error "File already exists: $resolvedPath. Use -Force to overwrite."
}
return
}
}

# Create directory if it doesn't exist
$directory = Split-Path -Path $resolvedPath -Parent
if ($directory -and -not (Test-Path -Path $directory -PathType Container)) {
Write-Verbose "Creating directory: $directory"
$null = New-Item -Path $directory -ItemType Directory -Force
}

# Format the JSON
if ($Compact) {
$formattedJson = $objectToExport | ConvertTo-Json -Depth $Depth -Compress
} else {
# Use Format-Json for consistent formatting
$formattedJson = Format-Json -InputObject $objectToExport -IndentationType $IndentationType -IndentationSize $IndentationSize
}

# Write to file
if ($PSCmdlet.ShouldProcess($resolvedPath, "Export JSON")) {
Write-Verbose "Exporting JSON to: $resolvedPath"

$writeParams = @{
Path = $resolvedPath
Value = $formattedJson
Encoding = $Encoding
}

# Only use Force for Set-Content if user explicitly requested it
if ($Force) {
$writeParams['Force'] = $true
}

Set-Content @writeParams -ErrorAction Stop

# Output file info object
Get-Item -Path $resolvedPath | Add-Member -MemberType NoteProperty -Name 'JsonExported' -Value $true -PassThru
}
} catch [System.ArgumentException] {
Write-Error "Invalid JSON format: $_"
} catch [System.IO.DirectoryNotFoundException] {
Write-Error "Directory not found or could not be created: $directory"
} catch [System.UnauthorizedAccessException] {
Write-Error "Access denied: $resolvedPath"
} catch {
Write-Error "Failed to export JSON to '$resolvedPath': $_"
}
}
}
2 changes: 1 addition & 1 deletion src/functions/public/Format-Json.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function Format-Json {
# Number of spaces or tabs per indentation level. Only used if not compacting.
[Parameter(ParameterSetName = 'FromString')]
[Parameter(ParameterSetName = 'FromObject')]
[UInt16]$IndentationSize = 4
[UInt16]$IndentationSize = 2
)

process {
Expand Down
Loading
Loading