在Powershell中将对象数组发送到API

时间:2014-08-15 19:57:59

标签: api powershell powershell-v4.0

我需要与期望一组对象的API以及其他参数进行交互。例如:

{
    "fields":  {
        "somefield": "somevalue",
        "someobject": {
            "name": "foobar"
        },
        "versions":  [
            {
                "name": "1.0"
            }
        ]
    }
}

this回答的帮助下,我尝试了两种不同的处理方法。我将它们组合成一个代码示例:

$versionName = New-Object -TypeName PSObject
$versionName | Add-Member -Name "name" -MemberType NoteProperty -Value "1.0"

$versionName2 = @{}
$versionName2.name = "1.0"

$postIssueBody = @{}
$postIssueBody.fields = @{}
$postIssueBody.fields.somefield = "somevalue"
$postIssueBody.fields.someobject = @{}
$postIssueBody.fields.someobject.name = "foobar"
$postIssueBody.fields.version = @($versionName)
$postIssueBody.fields.version2 = @()
$postIssueBody.fields.version2 += [pscustomobject]$versionName2

$postIssueRequestJson = $postIssueBody | ConvertTo-Json

$postIssueRequestJson

这导致以下输出:

{
    "fields":  {
        "somefield": "somevalue",
        "someobject": {
            "name": "foobar"
        },
        "version":  [
            "@{name=1.0}"
        ],
        "version2":  [
            "@{name=1.0}"
        ]
    }
}

正如您所看到的那样,它不会像有效的JSON一样飞行。处理此分配的最佳方法是什么,以便在通过ConvertTo-Json后正确形成版本名称?

2 个答案:

答案 0 :(得分:2)

ConvertTo-Json函数有一个名为Depth的开关。它通知Convert函数在将数据转换为JSON格式时应该有多深。默认情况下,它设置为2.由于未正确转换的数据位于3的深度,我们只需将深度设置为,如下所示:

$postIssueRequestJson = $postIssueBody | ConvertTo-Json -Depth 3

现在我们已经有了很好的JSON。

{
    "fields":  {
        "somefields":  "somevalue",
        "someobject":  {
            "name":  "foobar"
        },
        "versions":  [
            {
                "name":  "1.0"
            }
        ]
    }
}

答案 1 :(得分:-1)

好的,我想我明白了。所以你需要一个以"versions":开头的字符串,后跟一个对象数组,是吗?所以,让我们从一个空数组开始。

$Array = @()

然后我们可以创建对象,并将它们添加到数组中:

$Array += [PSCustomObject]@{"Name1"="1.0.0"}
$Array += [PSCustomObject]@{"Name2"="3.10.0"}

现在我们有一个带有PSCustomObjects的PowerShell数组。我们可以将它传递给ConvertTo-JSON,它将输出:

[
    {
        "Name1":  "1.0.0"
    },
    {
        "Name2":  "3.10.0"
    }
]

您想要的对象数组。如果你想让一个对象具有它的值,你可以简单地创建另一个对象:

$Versions = [PSCustomObject]@{'versions'=$Array}

然后,如果需要,可以将其转换为JSON:

{
    "versions":  [
                     {
                         "Name1":  "1.0.0"
                     },
                     {
                         "Name2":  "3.10.0"
                     }
                 ]
}

这就是你要找的,对吧?或者,如果你真的想要它在一条线上:

PS C:\> ($Versions|convertto-json).split() -join ""

{"versions":[{"Name1":"1.0.0"},{"Name2":"3.10.0"}]}

要完全按照你的第一个例子进行格式化,我们必须摆脱围绕这个结果的{},你可以用Trim()这样做:

PS C:\> ($Versions|convertto-json).trim("{}").split() -join ""

"versions":[{"Name1":"1.0.0"},{"Name2":"3.10.0"}]

编辑:好的,所以你只需要根据需要将对象添加为其他对象的属性值,就像我在我的示例中将数组设置为对象中的值一样。

我认为理解需要做的最简单的方法是采用你的例子(减去最后一个逗号,因为这会使它抛出错误),并将其传递给ConvertFrom-JSON并为其赋值变量。然后你可以看到Powersehll是如何形成的。一旦我这样做(我命名我的变量$ JSON),我可以看到$ JSON有1个'字段'的NoteProperty。 NoteProperty有3个NoteProperties的'somefield','someobject'和'versions'。当我做$JSON.fields|Get-Member时,我会发现更多有关这些内容的信息。

somefield只是一个字符串。这很容易处理。

someobject是一个PSCustomObject,基本上是一个HashTable,其中name = foobar。

版本只显示它是一个System.Object,所以我将执行$ JSON.fields.versions.GetType()并显示basetpe是System.Array。在查看版本后,它看起来像一个包含1个对象的数组,并且该对象有一个noteproperty是一个字符串(就像我们拥有的第一个对象)。

所以,有两种方法可以做到这一点。您可以尝试在线创建对象和数组,也可以提前创建它们,从最深的嵌套层开始,然后按照自己的方式进行操作。我会在晚些时候给你看。

$name = [PSCustomObject]@{'name'='1.0'}
$versions=@($name)
$Someobject = [PSCustomObject]@{'name'='foobar'}
$Fields = [PSCustomObject]@{
        'somefields'='somevalue'
        'someobject'=$someobject
        'versions'=$versions}
$NewJSON = [PSCustomObject]@{'Fields'=$fields}
$NewJSON | ConvertTo-Json