ps/Modules/Cole.PowerShell.Developer/Public/ConvertTo-Hashtable.ps1
2023-05-30 22:51:22 -07:00

117 lines
4.4 KiB
PowerShell

function ConvertTo-Hashtable {
<#
.SYNOPSIS
Used to convert an object into a hashtable
.EXAMPLE
$json | ConvertFrom-Json | ConvertTo-HashTable
.EXAMPLE
[xml]$someXmlVariable | ConvertTo-HashTable
.PARAMETER InputObject
This is the object to convert
.PARAMETER Recursing
This indicates that we are calling ourselves, so don't convert the intermediary objects to a PSCustomObject
.LINK
https://4sysops.com/archives/convert-json-to-a-powershell-hash-table/
#>
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param (
[Parameter(ValueFromPipeline)]
$InputObject,
[switch]$Recursing
)
# Return null if the input is null. This can happen when calling the function
# recursively and a property is null
if ($null -eq $InputObject) {
return $null
}
# We don't mess with existing hashtables
if ($InputObject -is [System.Collections.Hashtable]) {
return $InputObject
}
$properties = [System.Collections.Hashtable]@{}
# Let's get us some XML out of there heck yeah
if ($InputObject -is [System.Xml.XmlNode]) {
$properties = [System.Collections.Hashtable]@{}
$element = $InputObject
if ($element.HasAttributes) {
$properties.Attributes = [System.Collections.Hashtable]@{}
$attributes = $element.Attributes
foreach ($attribute in $attributes) {
$name = $attribute.Name
if (![string]::IsNullOrWhiteSpace($attribute.Prefix)){
$name = $name.Replace("$($attribute.Prefix):","")
}
$properties.Attributes[$name] = $attribute.Value
}
}
if (!$element.IsEmpty) {
# This should handle "innerText only" nodes as well
if ($element.HasChildNodes) {
$nodes = $element.ChildNodes
foreach ($node in $nodes) {
#Write-Host $node
$name = $node.Name
if (![string]::IsNullOrWhiteSpace($node.Prefix)){
$name = $name.Replace("$($node.Prefix):","")
}
if ($name -eq '#text') {
$properties["#text"] = $element.InnerText
} else {
$properties[$name] = (ConvertTo-Hashtable $node -Recursing)
}
}
} else {
# Was the next line but discovered those get handled above easily
# $properties["#text"] = $element.InnerText
}
}
if (![string]::IsNullOrWhiteSpace($element.BaseURI)) {
$properties["BaseURI"] = $element.BaseURI
}
if (![string]::IsNullOrWhiteSpace($element.NamespaceURI)) {
$prefix = "schema"
if (![string]::IsNullOrWhiteSpace($element.Prefix)) {
$prefix = $element.Prefix
}
$properties[$element.Prefix] = $element.NamespaceURI
}
} else {
# Check if the input is an array or collection. If so, we also need to convert
# those types into hash tables as well. This function will convert all child
# objects into hash tables (if applicable)
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
$collection = @(
foreach ($object in $InputObject) {
(ConvertTo-Hashtable -InputObject $object -Recursing)
}
)
# Return the array but don't enumerate it because the object may be pretty complex
Write-Output -NoEnumerate $collection
return
} elseif ($InputObject -is [psobject]) { # If the object has properties that need enumeration
# Convert it to its own hash table and return it
foreach ($property in $InputObject.PSObject.Properties.Where({$_.MemberType -eq 'NoteProperty' -or $_.MemberType -eq 'Property'})) {
$properties[$property.Name] = (ConvertTo-Hashtable -InputObject $property.Value -Recursing)
}
} else {
# If the object isn't an array, collection, or other object, just return it and hope for the best
return $InputObject
}
}
if ($Recursing) {
return $properties
} else {
return (New-Object PSCustomObject -Property $properties)
}
}