Skip to content

Instantly share code, notes, and snippets.

@rbleattler
Last active March 23, 2021 18:58
Show Gist options
  • Save rbleattler/83b4ec8c4a8caf5e984a11bf91593a8c to your computer and use it in GitHub Desktop.
Save rbleattler/83b4ec8c4a8caf5e984a11bf91593a8c to your computer and use it in GitHub Desktop.
Converts [HashTable]s to [PSCustomObject]s
function ConvertFrom-HashTable {
<#
.SYNOPSIS
This function will convert a hashtable to a [PSCustomObject]
.DESCRIPTION
This command will convert a hashtable to a [PSCustomObject]
.EXAMPLE
PS C:\> $HashTable
Name Value
---- -----
schemes {https, http}
securityDefinitions {petstore_auth, api_key}
info {license, termsOfService, version, title…}
swagger 2.0
host petstore.swagger.io
externalDocs {description, url}
paths {/user/logout, /user/{username}, /pet/{petId}, /user/createW…
tags {pet, store, user}
definitions {Order, ApiResponse, Pet, Category…}
basePath /v2
PS C:\> ConvertFrom-HashTable $HashTable -Recurse
schemes : {https, http}
securityDefinitions : @{petstore_auth=; api_key=}
info : @{license=; termsOfService=http://swagger.io/terms/; version=1.0.5;
title=Swagger Petstore; description=This is a sample server Petstore
server. You can find out more about Swagger at
[http://swagger.io](http://swagger.io) or on [irc.freenode.net,
#swagger](http://swagger.io/irc/). For this sample, you can use the
api key `special-key` to test the authorization filters.; contact=}
swagger : 2.0
host : petstore.swagger.io
externalDocs : @{description=Find out more about Swagger; url=http://swagger.io}
paths : @{/user/logout=; /user/{username}=; /pet/{petId}=;
/user/createWithArray=; /pet/{petId}/uploadImage=;
/user/createWithList=; /pet=; /store/inventory=; /user=;
/user/login=; /pet/findByTags=; /pet/findByStatus=; /store/order=;
/store/order/{orderId}=}
tags : {@{externalDocs=@{description=Find out more; url=http://swagger.io};
description=Everything about your Pets; name=pet}, @{name=store;
description=Access to Petstore orders},
@{externalDocs=@{description=Find out more about our store;
url=http://swagger.io}; description=Operations about user; name=user}}
definitions : @{Order=; ApiResponse=; Pet=; Category=; User=; Tag=}
basePath : /v2
The hashtable stored in variable $HashTable was converted to a PSCustomObject
.INPUTS
HashTable
.OUTPUTS
PSCustomObject
.PARAMETER InputObject
Hashtable to be converted
.PARAMETER Direct
Does *NOT* try to use ConvertFrom/To-Json
.PARAMETER Recurse
When enabled, converts all nested hashtables as well.
.PARAMETER Transcript
Enables logging function ($ENV:Temp)
#>
[OutputType([PSCustomObject])]
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[hashtable]
$InputObject,
[Parameter()]
[switch]
$Direct,
[Parameter()]
[switch]
$Transcript,
[Parameter()]
[switch]
$Recurse,
[Parameter(DontShow)]
[switch]
$IsRecurse
)
begin {
Write-Debug "Enter [$($PSCmdlet.MyInvocation.MyCommand.Name)]..."
$PSBoundParameters.Keys | ForEach-Object {
if ($PSBoundParameters.$PSItem -is [string]) {
Write-Debug "[$($PSCmdlet.MyInvocation.MyCommand.Name)] $_ : $($PSBoundParameters.Item($_))"
} else {
Write-Debug "[$($PSCmdlet.MyInvocation.MyCommand.Name)] $_ : $($PSBoundParameters.Item($_).GetType())"
}
}
if (-not $IsRecurse -and $Transcript) {
if ([string]::IsNullOrWhiteSpace($LogPath)) {
$LogPath = $ENV:Temp
}
$ScriptName = $PSCmdlet.MyInvocation.MyCommand.Name.Split("`.ps")[0]
$Now = Get-Date -Format yyyyMMdd_hh-mm-ss
$ScriptLogName = '{0}.{1}.txt' -f $Now, $ScriptName
$ScriptLog = Join-Path -Path $LogPath -ChildPath $ScriptLogName
Start-Transcript -Path $ScriptLog -Verbose -Force | Out-Null
}
function Convert-Recurse {
[CmdletBinding()]
param (
[Parameter(Mandatory, ValueFromPipeline, Position = 0)]
[hashtable]
$InputObject,
[Parameter(Position = 1)]
[switch]
$Recurse,
[Parameter(DontShow, Position = 2)]
[switch]
$IsRecurse,
[Parameter()]
[switch]
$Direct
)
begin {
Write-Debug "Enter [$($PSCmdlet.MyInvocation.MyCommand.Name)]..."
$PSBoundParameters.Keys | ForEach-Object {
if ($PSBoundParameters.$PSItem -is [string]) {
Write-Debug "[$($PSCmdlet.MyInvocation.MyCommand.Name)] $_ : $($PSBoundParameters.Item($_))"
} else {
Write-Debug "[$($PSCmdlet.MyInvocation.MyCommand.Name)] $_ : $($PSBoundParameters.Item($_).GetType())"
}
}
}
process {
$PSBoundParameters.Item('IsRecurse') = $true
$PSBoundParameters.Item('Recurse') = $true
$PSBoundParameters.Item('Direct') = $true
ConvertFrom-HashTable @PSBoundParameters
}
end {
Write-Debug "Exit [$($PSCmdlet.MyInvocation.MyCommand.Name)]..."
}
}
function Convert-Array {
[CmdletBinding()]
param (
[array]
$InputObject
)
begin {
Write-Debug "Enter [$($PSCmdlet.MyInvocation.MyCommand.Name)]..."
$PSBoundParameters.Keys | ForEach-Object {
if ($PSBoundParameters.$PSItem -is [string]) {
Write-Debug "[$($PSCmdlet.MyInvocation.MyCommand.Name)] $_ : $($PSBoundParameters.Item($_))"
} else {
Write-Debug "[$($PSCmdlet.MyInvocation.MyCommand.Name)] $_ : $($PSBoundParameters.Item($_).GetType())"
}
}
}
process {
$InputObject.ForEach{
if ($PSItem -is [hashtable]) {
Convert-Recurse -InputObject $PSItem
} elseif ($PSItem -is [array]) {
Convert-Array $PSItem
} elseif ($PSItem -is [string]) {
$PSItem
}
}
}
end {
Write-Debug "Exit [$($PSCmdlet.MyInvocation.MyCommand.Name)]..."
}
}
}
process {
If ((Get-Command ConvertFrom-Json -ErrorAction SilentlyContinue) -and ($Recurse) -and (-not $Direct)) {
$InputObject | ConvertTo-Json | ConvertFrom-Json
} else {
$OutputObject = [PSCustomObject]::new()
$InputObject.Keys | ForEach-Object {
Write-Debug -Message "[$($PSCmdlet.MyInvocation.MyCommand.Name)] Converting $PSItem" | Out-Null
$TargetValue = $InputObject.$PSItem
if ($TargetValue -is [string]) {
$ConvertedString = try {
$TargetValue | ConvertFrom-StringData
} catch {
$TargetValue
}
if ($ConvertedString -is [string]) {
$TargetValue = $ConvertedString
} elseif ($TargetValue -is [array]) {
$TargetValue = Convert-Array -InputObject $TargetValue
} elseif ($TargetValue -is [hashtable]) {
$TargetValue = Convert-Recurse -InputObject $TargetValue
}
} elseif ($TargetValue -is [array]) {
Write-Debug -Message "[$($PSCmdlet.MyInvocation.MyCommand.Name)] Target is Array!" | Out-Null
$TargetValue = Convert-Array -InputObject $TargetValue
} elseif ($TargetValue -is [hashtable] -and $Recurse) {
$TargetValue = Convert-Recurse -InputObject $TargetValue
} elseif ($TargetValue -is [hashtable] -and -not $Recurse) {
$TargetValue = ConvertFrom-HashTable -InputObject $TargetValue
}
if ($PSItem -in $OutputObject.PSObject.Properties.Name -or $PSItem -ceq 'value') {
$Name = '_{0}' -f $PSItem
} else {
$Name = $PSItem
}
$OutputObject | Add-Member -MemberType NoteProperty -Name $Name -Value $TargetValue
}
}
}
end {
if (-not $IsRecurse -and $Transcript) {
Stop-Transcript -Verbose | Out-Null
}
$OutputObject
Write-Debug "Exit [$($PSCmdlet.MyInvocation.MyCommand.Name)]..."
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment