utilities/pipelines/sharedScripts/helper/ConvertTo-OrderedHashtable.ps1 (98 lines of code) (raw):
#requires -version 7.3
<#
.SYNOPSIS
Convert a given JSON string into an ordered HashTable.
.DESCRIPTION
Convert a given JSON string into an ordered HashTable.
.PARAMETER JSONInputObject
Mandatory. The JSON string to convert into an ordered HashTable object.
.EXAMPLE
ConvertTo-OrderedHashtable -JSONInputObject "@{ b = 'b'; a = 'a' ; c = @( 3, 1, 2 )}"
Convert the given JSON string into a sorted HashTable. Would return the HashTable:
@{
a = 'a'
b = 'b'
c = @(
1,
2,
3
)
}
.EXAMPLE
ConvertTo-OrderedHashtable -JSONInputObject '{"elem":[3,1,2,"a",{"a":"a","b":"b"},[23,1],["23","1"]],"arr":["one"]}'
Convert the given JSON string into a sorted HashTable. Would return the HashTable:
@{
arr = @('one')
elem = @(
1,
@(
1,
23
),
@(
'1',
'23'
)
2,
3,
'a'
)
}
#>
function ConvertTo-OrderedHashtable {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string] $JSONInputObject # Must be string to workaround auto-conversion
)
$JSONObject = ConvertFrom-Json $JSONInputObject -AsHashtable -Depth 99 -NoEnumerate
$orderedLevel = [ordered]@{}
if (-not ($JSONObject.GetType().BaseType.Name -eq 'Hashtable')) {
return $JSONObject # E.g. in primitive data types [1,2,3]
}
foreach ($currentLevelKey in ($JSONObject.Keys | Sort-Object -Culture 'en-US')) {
if ($null -eq $JSONObject[$currentLevelKey]) {
# Handle case in which the value is 'null' and hence has no type
$orderedLevel[$currentLevelKey] = $null
continue
}
switch ($JSONObject[$currentLevelKey].GetType().BaseType.Name) {
{ $PSItem -in @('Hashtable') } {
$orderedLevel[$currentLevelKey] = ConvertTo-OrderedHashtable -JSONInputObject ($JSONObject[$currentLevelKey] | ConvertTo-Json -Depth 99)
}
'Array' {
$arrayOutput = @()
# Case: Array of arrays
$arrayElements = $JSONObject[$currentLevelKey] | Where-Object { $_.GetType().BaseType.Name -eq 'Array' }
foreach ($array in $arrayElements) {
if ($array.Count -gt 1) {
# Only sort for arrays with more than one item. Otherwise single-item arrays are casted
$array = $array | Sort-Object -Culture 'en-US'
}
$arrayOutput += , (ConvertTo-OrderedHashtable -JSONInputObject ($array | ConvertTo-Json -Depth 99))
}
# Case: Array of objects
$hashTableElements = $JSONObject[$currentLevelKey] | Where-Object { $_.GetType().BaseType.Name -eq 'Hashtable' }
foreach ($hashTable in $hashTableElements) {
$arrayOutput += , (ConvertTo-OrderedHashtable -JSONInputObject ($hashTable | ConvertTo-Json -Depth 99))
}
# Case: Primitive data types
$primitiveElements = $JSONObject[$currentLevelKey] | Where-Object { $_.GetType().BaseType.Name -notin @('Array', 'Hashtable') } | ConvertTo-Json -Depth 99 | ConvertFrom-Json -AsHashtable -NoEnumerate -Depth 99
if ($primitiveElements.Count -gt 1) {
$primitiveElements = $primitiveElements | Sort-Object -Culture 'en-US'
}
$arrayOutput += $primitiveElements
if ($array.Count -gt 1) {
# Only sort for arrays with more than one item. Otherwise single-item arrays are casted
$arrayOutput = $arrayOutput | Sort-Object -Culture 'en-US'
}
$orderedLevel[$currentLevelKey] = $arrayOutput
}
Default {
# string/int/etc.
$orderedLevel[$currentLevelKey] = $JSONObject[$currentLevelKey]
}
}
}
return $orderedLevel
}