使用Powershell数组、哈希表和JSON

iq0todco  于 4个月前  发布在  Shell
关注(0)|答案(1)|浏览(71)

我目前正在做一个项目,开发PowerShell命令来管理我公司生产的一个设备。该设备响应各种不同的API来实现其所有功能。
我目前在将一组字符串转换为正确的格式时遇到了一个问题,这样当我ConvertTo-JSON时就可以正确输出了。
我已经让它工作了,但我不得不在最后做一些字符串操作。我相信有一种方法可以正确地做到这一点,但我找不到解决方案。这不是最漂亮的解决方案,但它目前工作。我希望有人有另一个想法,或者只是我错过了一些东西。
问题出在CSR的主题部分。
我的API需要:

"names": [
        {
            "C": string,
            "L": string,
            "O": string,
            "OU": string,
            "ST": string
        }

字符串
我似乎不能让它“干净”地工作
下面是我的设备正在为API调用查找的模式。

{
    "cn": string,
    "algorithm": string,
    "dnsNames": [
        string
    ],
    "emailAddresses": [
        string
    ],
    "encryptionAlgo": string,
    "ipAddresses": [
        string
    ],
    "name": string,
    "names": [
        {
            "C": string,
            "L": string,
            "O": string,
            "OU": string,
            "ST": string
        }
    ],
    "password": string,
    "privateKeyBytes": string,
    "size": integer
}


下面是我的函数:

function New-ConnectionCSR {
param (
    [Parameter(Mandatory=$true)] [string] $name,
    [Parameter()] [string] $cn=$name,
    [Parameter()] [string] $algorithm="RSA",
    [Parameter()] [int] $size=2048,
    [Parameter()] [string[]] $dnsNames,
    [Parameter()] [string[]] $ipAddresses,
    [Parameter()] [string[]] $emailAddresses,
    [Parameter()] [Alias('organization','org')] [string] $o="",
    [Parameter()] [Alias('oganizationalunit')] [string] $ou="",
    [Parameter()] [Alias('location','locality')] [string] $l="",
    [Parameter()] [Alias('state')] [string] $st="",
    [Parameter()] [Alias('country')] [string] $c=""
    )

    Write-Debug "Start: $($MyInvocation.MyCommand.Name)"

    # Mandatory Parameters
    $body=@{
        
        "name"          = $name
        "cn"            = $cn
        "algorithm"     = $algorithm
        "names"         = @()

    }

    #Optional Parameters
    if($size){$body.Add('size',$size)}
    if($dnsNames){
        $dnsNames = $dnsNames.Split(",")
        $body.Add('dnsNames',$dnsNames)
    }
    if($ipAddresses){
        $ipAddresses = $ipAddresses.Split(",")
        $body.Add('ipAddresses',$ipAddresses)
    }
    if($emailAddresses){
        $emailAddresses = $emailAddresses.Split(",")
        $body.Add('emailAddresses',$emailAddresses)
    }
    if($ou -or $o -or $l -or $st -or $c){
        $names = @()
        if($ou){ $names += ('"ou":"' + $ou + '"') }
        if($o){ $names += ('"o":"' + $o + '"') }
        if($l){ $names += ('"l":"' + $l + '"') }
        if($st){ $names += ('"st":"' + $st + '"') }   
        if($c){ $names += ('"c":"' + $c + '"') }
               
        $body.names += "{ $(($names -join ",")) }"
    }

    $jsonBody = ($body | ConvertTo-Json).Replace('\"','"')
    $jsonBody = $jsonBody.Replace('"{','{')
    $jsonBody = $jsonBody.Replace('}"','}')
    
    Write-Debug "JSON Body:`n$($jsonBody)"
}

注意最后的字符串操作。这是我不想要的。

在最后一行之后,我执行所有的API调用,但是代码应该像函数一样工作,并输出JSON Body。
最后,下面是我用来调用的命令:

New-ConnectionCSR -name "MyConnectionCert" -cn "mydevice.local" -size 2048 -dnsNames "mydevice.contoso.com,mydevice.contoso.local" -ipAddresses "10.0.0.1" -emailAddresses "[email protected]" -ou "MyOU" -o "MyOrg" -l "MyCity" -st "FDL" -c "USA"

2ledvvac

2ledvvac1#

如果你将函数的中间块改为这个,它应该可以工作。

...

    if($ou -or $o -or $l -or $st -or $c){
        $dn = [ordered] @{}
        if($c)  { $dn.C  = $c  }
        if($l)  { $dn.L  = $l  }
        if($o)  { $dn.O  = $o  }
        if($ou) { $dn.OU = $ou }
        if($st) { $dn.ST = $st }

        $body.names = @( $dn )
    }

    $jsonBody = $body | ConvertTo-Json

...

字符串
而不是构建一个字符串数组,你构建一个(有序的)键值对字典- PowerShell会很高兴地将其干净地转换为json,而不需要任何进一步的工作。

...
  "names": [
    {
      "C": "USA"
      "L": "MyCity",
      "O": "MyOrg",
      "OU": "MyOU",
      "ST": "FDL"
    }
  ],
...


(我使用$dn作为临时变量,因为它看起来像是在为X509证书构建一个可分辨名称。
顺便说一句,如果你想控制根对象属性的顺序,你可以这样做,使$body也成为一个 * 有序 * 字典,而不是哈希表-这样你的json属性将以可预测的顺序发出:

$body = [ordered] @{
   ... etc ...
}

相关问题