Working with Graph API and Intune. I create hash table in my script and covert it to JSON which POST to GraphAPI. But in one case during conversion I lose array. Because of this GraphAPI does not want to accept JSON and returns error.
Case when conversion is correct:
$TargetGroupIDs = @('111', '222')
$AppAssignment = @{
mobileAppAssignments = @{
}
}
$AppAssignment.mobileAppAssignments = foreach ($GroupID in $TargetGroupIDs) {
$Hash = [ordered]@{
"@odata.type" = "#microsoft.graph.mobileAppAssignment"
intent = "Required"
settings = $null
target = @{
"@odata.type" = "#microsoft.graph.groupAssignmentTarget"
groupId = "$GroupID"
}
}
write-output (New-Object -Typename PSObject -Property $hash)
}
$AppAssignment | ConvertTo-Json -Depth 50
Output:
{
"mobileAppAssignments": [
{
"@odata.type": "#microsoft.graph.mobileAppAssignment",
"intent": "Required",
"settings": null,
"target": {
"groupId": "111",
"@odata.type": "#microsoft.graph.groupAssignmentTarget"
}
},
{
"@odata.type": "#microsoft.graph.mobileAppAssignment",
"intent": "Required",
"settings": null,
"target": {
"groupId": "222",
"@odata.type": "#microsoft.graph.groupAssignmentTarget"
}
}
]
}
But when I have one element in $TargetGroupIDs conversion is not correct:
$TargetGroupIDs = @('111')
$AppAssignment = @{
mobileAppAssignments = @{
}
}
$AppAssignment.mobileAppAssignments = foreach ($GroupID in $TargetGroupIDs) {
$Hash = [ordered]@{
"@odata.type" = "#microsoft.graph.mobileAppAssignment"
intent = "Required"
settings = $null
target = @{
"@odata.type" = "#microsoft.graph.groupAssignmentTarget"
groupId = "$GroupID"
}
}
write-output (New-Object -Typename PSObject -Property $hash)
}
$AppAssignment | ConvertTo-Json -Depth 50
Output:
{
"mobileAppAssignments": {
"@odata.type": "#microsoft.graph.mobileAppAssignment",
"intent": "Required",
"settings": null,
"target": {
"groupId": "111",
"@odata.type": "#microsoft.graph.groupAssignmentTarget"
}
}
}
Please note difference in brackets after mobileAppAssignments. In first case [], but in second case {}.
Could someone tell what I am missing in second case?
CodePudding user response:
Theo and Santiago Squarzon have provided the crucial hint in the comments, but let me spell it out:
To ensure that the output from your foreach
statement is an array, enclose it in @()
, the array-subexpression operator:
$AppAssignment.mobileAppAssignments = @(
foreach ($GroupID in $TargetGroupIDs) {
[pscustomobject] @{
"@odata.type" = "#microsoft.graph.mobileAppAssignment"
intent = "Required"
settings = $null
target = @{
"@odata.type" = "#microsoft.graph.groupAssignmentTarget"
groupId = "$GroupID"
}
}
}
)
Also note that simplified syntax custom-object literal syntax ([pscustomobject] @{ ... }
).
@(...)
ensures that an array (of type [object[]]
) is returned, irrespective of how many objects, if any, the foreach
statement outputs.
Without @(...)
, the data type of the collected output depends on the number of output objects produced by a statement or command:
If there is no output object, the special "AutomationNull" value is returned, which signifies the absence of output; this special value behaves like an empty collection in enumeration contexts, notably the pipeline, and like
$null
in expression contexts - see this answer for more information; in the context at hand, it would be converted to anull
JSON value.If there is one output object, it is collected as-is, as itself - this is what you saw.
Only with two or more output objects do you get an array (of type
[object[]]
).
Note: The behavior above follows from the streaming behavior of the PowerShell pipeline / its success output stream: object are emitted one by one, and needing to deal with multiple objects only comes into play if there's a need to collect output objects: see this answer for more information.