I've got a function that returns a hashtable and i need to transform the keys into nested objects, but i am losing my mind.
here is a hardcoded example of the hashtable I'm dealing with
# $hash = SomeFunctionThatReturnsAhashTable
$hash = @{
'root.Blubb' = @(5)
'root.controller.haha' = 'hoho', 'hoho'
'root.controller.hugo' = @(12)
'root.controller.name' = '10.3.3.171', '10.3.3.172'
'root.controller.renate' = @(123)
'root.controller.test' = 2, 2
'root.controller.upsala' = @('handy')
'root.t.t1.wert' = @(1)
'root.t.t2.wert' = @(2)
'root.test' = 1, 2
}
the following is the idea of what i want the hashtable to be transformed into
$obj = [pscustomobject]@{
root = [pscustomobject]@{
Blubb = @(5)
controller = [pscustomobject]@{
haha = 'hoho', 'hoho'
hugo = @(12)
name = '10.3.3.171', '10.3.3.172'
renate = @(123)
test = 2, 2
upsala = @('handy')
}
t = [pscustomobject]@{
t1 = [pscustomobject]@{
wert = @(1)
}
t2 = [pscustomobject]@{
wert = @(2)
}
}
test = 1, 2
}
}
I'm trying to split on the '.' and return sub-objects, but i don't know how to get it done. If there's a better way to go about this, please let me know. this is what i have so far.
function keytoobject ($key, $value) {
if ($key.contains('.')) {
[pscustomobject]@{
($key.substring($key.indexof('.')+1)) = (keytoobject $key.substring($key.indexof('.')+1) $value)
}
} else {
[pscustomobject]@{
$key = $value
}
}
}
$hash.Keys | % {
keytoobject $_ ($hash[$_])
}
any help would be greatly appreciated.
Oh my gosh! I have been working on this for a few hours now but I think I have something that is working. I had to use Add-Member more than I would have liked but it was the way I got to create empty objects so they would not be equal to $null. That was important because that test determined with new nested object need be created.
function Add-NestedObject($sourceObject, $path, $objectData){
# This function will add the object $objectToNest into $sourceObject into the location named by $parentPath
$currentPath,$remainingPath = $path.Split(".",2)
# Check to see if the object contains the following subproperty.
if($sourceObject.$currentPath -eq $null){
# This property does not exist and needs to be created. Use an empty object
Add-Member -Name $currentPath -TypeName PSObject -InputObject $sourceObject -MemberType NoteProperty -Value (New-Object -TypeName PSObject)
}
# Are there more elements to this path?
if($remainingPath){
# There are more nested objects. Keep passing data until we get to the point where we can populate it.
Add-NestedObject ($sourceObject.$currentPath) $remainingPath $objectData
} else {
# Now we can use the data and populate this object.
$props = @{}
$objectData | ForEach-Object{
$_.Name = $_.Name.Split(".")[-1]
$props.($_.Name) = $_.Value
}
# Set the current path in the object to contain the data we have been passing.
$sourceObject.$currentPath = [pscustomobject]$props
}
}
$schema = $hash.GetEnumerator() |
Select-Object Name,Value,@{Name="Parent";Expression={$split = $_.Name -split "\.";$split[0..($split.Count - 2)] -join "."}} |
Group-Object Parent | Sort-Object Name
# Empty Object to start
$object = New-Object -TypeName PSObject
# Build the object skeleton
$schema | ForEach-Object{Add-NestedObject $object $_.Name $_.Group}
# Show the monstrosity
$object
The basics is that we use group object to collect all of the values into there parent properties. They for each of those parent properties we create each node in the path (assuming that it does not already exist) using a recursive function. Once we create all the nodes then we can place the value collection inside that node.
The value collection is rebuilt as a custom object and assigned to the end node.
Here is what the thing looks like as JSON just so you can see what the object looks like now that it is converted.
{
"root": {
"test": [
1,
2
],
"Blubb": [
5
],
"controller": {
"name": [
"10.3.3.171",
"10.3.3.172"
],
"haha": [
"hoho",
"hoho"
],
"hugo": [
12
],
"test": [
2,
2
],
"upsala": [
"handy"
],
"renate": [
123
]
},
"t": {
"t1": {
"wert": [
1
]
},
"t2": {
"wert": [
2
]
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With