Public/Collections/ConvertTo-RequestBody.ps1
|
<#
.SYNOPSIS Builds a request body hashtable from a function's bound parameters. .DESCRIPTION Loops through the calling function's parameter metadata and adds every parameter that was actually bound (present in $PSBoundParameters) to the returned hashtable, keyed by its JSON name: - A parameter decorated with [BodyProperty('json_name')] is keyed by that name. - A parameter with no [BodyProperty()] attribute is keyed by its own name in lowercase (e.g. -Name becomes 'name'). - A parameter decorated with [BodyIgnore()] is skipped entirely. Use this for route/path parameters such as -Id or -CompanyId that belong in the URL rather than the body. - PowerShell's common parameters (-Verbose, -WhatIf, -ErrorAction, etc.) are always skipped. Value types (int, bool, switch, etc.) are always included when bound, even when they hold their default value, so -Enabled:$false is sent as false. Reference types (strings, arrays, objects) are only included when Test-HasValue returns $true, so an empty string or empty array is dropped. .PARAMETER BoundParameters The $PSBoundParameters dictionary from the calling function. .PARAMETER ParameterMetadata The calling function's parameter metadata, typically $MyInvocation.MyCommand.Parameters. .EXAMPLE function Set-HuduWidget { [CmdletBinding(SupportsShouldProcess)] param( [BodyIgnore()] [Parameter(Mandatory)] [int] $Id, [Parameter()] [string] $Name, [BodyProperty('company_id')] [Parameter()] [int] $CompanyId ) $body = ConvertTo-RequestBody -BoundParameters $PSBoundParameters -ParameterMetadata $MyInvocation.MyCommand.Parameters } Set-HuduWidget -Id 7 -Name 'Core Switch' -CompanyId 5 Inside the function, $body is @{ name = 'Core Switch'; company_id = 5 }. -Id is excluded by [BodyIgnore()], -Name falls back to its lowercase parameter name, and -CompanyId uses the name from [BodyProperty()]. .OUTPUTS System.Collections.Hashtable #> function ConvertTo-RequestBody { [OutputType([hashtable])] [CmdletBinding()] param( [Parameter(Mandatory)] [System.Collections.IDictionary] $BoundParameters, [Parameter(Mandatory)] [System.Collections.Generic.Dictionary[string, System.Management.Automation.ParameterMetadata]] $ParameterMetadata ) # PowerShell's built-in parameters (-Verbose, -WhatIf, -ErrorAction, etc.) show up in both # ParameterMetadata and PSBoundParameters just like the function's own parameters, so they # have to be excluded explicitly - there's no metadata flag that marks them as "common". $commonParams = [System.Management.Automation.Cmdlet]::CommonParameters + [System.Management.Automation.Cmdlet]::OptionalCommonParameters $body = @{} foreach ($paramName in $ParameterMetadata.Keys) { if ($commonParams -contains $paramName) { continue } if (-not $BoundParameters.ContainsKey($paramName)) { continue } $attributes = $ParameterMetadata[$paramName].Attributes if ($attributes | Where-Object { $_ -is [BodyIgnore] }) { continue } $value = $BoundParameters[$paramName] if ($value -isnot [ValueType] -and -not (Test-HasValue -Value $value)) { continue } $bodyAttr = $attributes | Where-Object { $_ -is [BodyProperty] } | Select-Object -First 1 $key = if ($null -ne $bodyAttr) { $bodyAttr.Name } else { $paramName.ToLowerInvariant() } $body[$key] = $value } return $body } |