PowerShell将Hashtable转换为JSON后缺少数组

3

使用 Graph API 和 Intune。我在脚本中创建哈希表并将其转换为 JSON,然后通过 POST 请求发送到 GraphAPI。

但是,在某些情况下,转换过程中会丢失数组。因此,GraphAPI 不接受 JSON 并返回错误。

当转换正确时的情况:

$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

输出:

{
  "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"
      }
    }
  ]
}

但是当$TargetGroupIDs中只有一个元素时,转换不正确:

$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

输出:

{
  "mobileAppAssignments": {
    "@odata.type": "#microsoft.graph.mobileAppAssignment",
    "intent": "Required",
    "settings": null,
    "target": {
      "groupId": "111",
      "@odata.type": "#microsoft.graph.groupAssignmentTarget"
    }
  }
}

请注意mobileAppAssignments后面括号的不同。第一种情况是[], 而第二种情况是{}。
有人能告诉我第二种情况缺少了什么吗?

6
将您的 foreach 循环用数组子表达式运算符括起来:$AppAssignment.mobileAppAssignments = @(foreach ($GroupID in $TargetGroupIDs) { ... }) - Theo
1
或者使用.ForEach内置方法替换foreach,该方法始终输出类似数组的集合:$AppAssignment.mobileAppAssignments = $TargetGroupIDs.ForEach{,并将$GroupID替换为$_ - zett42
1个回答

3

TheoSantiago Squarzon 在评论中提供了关键提示,但让我来解释一下:

为了确保你的 foreach 语句的输出是一个 数组,请使用 @() 包含它,这是 数组子表达式运算符

$AppAssignment.mobileAppAssignments = @(
  foreach ($GroupID in $TargetGroupIDs) {
    [pscustomobject] @{
      "@odata.type" = "#microsoft.graph.mobileAppAssignment"
      intent        = "Required"
      settings      = $null
      target        = @{
        "@odata.type" = "#microsoft.graph.groupAssignmentTarget"
        groupId       = "$GroupID"
      }
    }
  }
)

请注意,还有一种简化语法的自定义对象文字语法([pscustomobject] @{ ... })。 @(...) 确保返回一个数组(类型为 [object[]]),不管 foreach 语句输出多少个对象。 如果没有使用 @(...),则收集的输出数据类型取决于语句或命令产生的 输出对象数量
  • 如果没有输出对象,则返回特殊值“AutomationNull”,表示输出不存在;在枚举情境(尤其是管道)中,此特殊值的行为类似于空集合,在表达式情境中则类似于$null - 更多信息请参见this answer; 在这种情况下,它将被转换为null JSON值。

  • 如果有 一个 输出对象,则按原样收集该对象本身 - 这是您看到的。

  • 仅当有 两个或更多 输出对象时,才会得到一个 数组(类型为[object[]])。

注意:上述行为源自PowerShell管道/其成功输出流的流式行为:对象逐个发出,并且只有在需要收集输出对象时才需要处理多个对象:有关更多信息,请参见this answer

感谢您详细的回复。我不仅解决了我的问题,还理解了根本原因。 - Vindi4i
很高兴听到这个消息,@Vindi4i;感谢您的反馈。 - mklement0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接