我正在编写一个脚本,通过API修改现有对象的安全性.我可以很容易地抓取对象,以及分配给它们的用户/组列表.但是,我需要解析这些数据,并将任何不匹配的用户/组添加到一个新的JSON主体中,以便在POST请求中发送回go .我为此创建了两个函数.一个用于创建JSON主体,另一个用于添加到JSON主体的删除部分.然而,它并没有像我期望的那样将id/type添加到remove部分,因为JSON的remove部分在每次迭代之后都保持为空.

我错过了什么吗?

function Build-JsonBody {
    param (
        [string]$defaultSecurity,
        [array]$include,
        [array]$remove
    )

    $jsonBody = @{
        "default_security" = $defaultSecurity
        "include"          = $include
        "remove"           = $remove
    }

    return $jsonBody
}

function Add-ToRemoveSection {
    param (
        [ref]$removeSection,
        [string]$id,
        [string]$type
    )

    $itemToRemove = @{
        "id"   = $id
        "type" = $type
    }

    $removeSection.Value += $itemToRemove
}

Write-Host "Finding all workspaces with Matter #$matter_num..."
$ws_search_url = $baseurl + "/work/api/v2/customers/$customer_id/libraries/ABC/workspaces?custom2=$matter_num"
$ws_resp = Invoke-RestMethod -Uri $ws_search_url -Headers $header -Method Get -ContentType "application/json"
$ws_results = $ws_resp.data.results

# For each workspace returned, look at the list of users, groups, and default security
foreach($ws in $ws_results){
    $id = $ws.id
    $sec_search_url = $baseurl + "/work/api/v2/customers/$customer_id/libraries/ABC/workspaces/ABC!164/security"
    $sec_resp = Invoke-RestMethod -Uri $sec_search_url -Headers $header -Method Get -ContentType "application/json"
    $sec_results = $sec_resp.data.results
    $jsonBody = Build-JsonBody -defaultSecurity "private" -include @(@{ "id" = "ADMIN_USERS"; "access_level" = "full_access"; "type" = "group" }) -remove @()

    # Iterate through the source data
    foreach ($item in $sec_results) {
        if ($item.id -ne "ADMIN_USERS") {
            # For "user" type, add to the "remove" section
            Add-ToRemoveSection -removeSection ([ref]$jsonBody.remove) -id $item.id -type $item.type
        }
        }
    }         
    
    #Convert body to JSON
    $jsonBodyJson = $jsonBody | ConvertTo-Json -Depth 10
    Write-Host $jsonBodyJson

推荐答案

您遇到此问题的主要原因是,数组是固定大小的集合,当您对一个数组执行+=时,PowerShell会创建一个新数组,并将其所有内容与您要添加的项一起复制.在您的函数中,即使不使用[ref],也会为变量$removeSection分配与$jsonBody.remove相同的引用,但是,当添加新项+=时,该引用将丢失,并为$removeSection分配一个新array.

$arr = @()
& { param($i) $i += 1 } -i $arr
$arr # nothing

您的解决方法可能是将保存数组($jsonBody)的哈希表作为参数传递:

$jsonbody = @{ remove = @() }
& { param($i) $i.remove += 1 } $jsonBody
$jsonBody

# Name                           Value
# ----                           -----
# remove                         {1}

或者,您可以使用collection that allows you to add items to it:

$list = [System.Collections.Generic.List[int]]::new()
& { param($i) $i.Add(1) } $list
$list # 1

如果使用List<T>,您的函数可能是:

function Build-JsonBody {
    param (
        [string] $defaultSecurity,
        [System.Collections.Generic.List[hashtable]] $include,
        [System.Collections.Generic.List[hashtable]] $remove
    )

    @{
        'default_security' = $defaultSecurity
        'include'          = $include
        'remove'           = $remove
    }
}

function Add-ToRemoveSection {
    param (
        [System.Collections.Generic.List[hashtable]] $removeSection,
        [string] $id,
        [string] $type
    )

    $removeSection.Add(@{
        'id'   = $id
        'type' = $type
    })
}

那么,它应该运行得很好:

$jsonBody = Build-JsonBody -defaultSecurity 'private' -include @() -remove @()
Add-ToRemoveSection -removeSection $jsonBody['remove'] -id 'foo' -type 'bar'
Add-ToRemoveSection -removeSection $jsonBody['remove'] -id 'baz' -type '123'
$jsonBody['remove']

# Name                           Value
# ----                           -----
# id                             foo
# type                           bar
# id                             baz
# type                           123

还有一种更简单、更简单的方法,那就是根本不使用函数,只需在循环中操作$jsonBody,并将内部循环的结果赋给remove键:

foreach ($ws in $ws_results) {
    # some code goes before this
    $jsonBody = Build-JsonBody # .....

    # Iterate through the source data
    $toRemove = foreach ($item in $sec_results) {
        if ($item.id -ne 'ADMIN_USERS') {
            @{
                id   = $item.id
                type = $item.type
            }
        }
    }

    $jsonBody['remove'] = @($toRemove)
}

Json相关问答推荐

如何从一个700MB的json文件中列出PowerShell中的所有密钥?

使用 JOLT 将日期格式转换为 JSON

震动范围改善

Vega-Lite规范:尽管在规范中提供了数据,但显示空图表

APIM 生成 JsonArray 到 EventHub

Powershell - 如何从 JSON 中删除/过滤元素但保留其余部分?

使用 KQL 和外部 data() 运算符从 json 文件中提取信息

如何在生产环境中更改 Flutter 应用程序中的数据模型?

Json.NET SerializeObject 转义值以防止 XSS

从ruby中的json获取特定的键值

以 JSON 格式访问(新型、公共)Google 工作表

Angularjs访问本地json文件

如何在golang中获取 struct 的json字段名称?

如何使用 Newtonsoft.Json 反序列化 JSON 数组

Newtonsoft Json 将值 {null} 转换为类型System.Int32时出错

在 Jersey 服务中使用 JSON 对象

使用 Python 3 读取 JSON 文件

使用适用于 Python 的 Google API - 我从哪里获取 client_secrets.json 文件?

如何将 MongoDB 查询转换为 JSON?

JSON 模式 - 如果对象*不*包含特定属性则有效