I\'m trying to push data to a REST api using powershell.
http://influxdb.com/docs/v0.8/api/reading_and_writing_data.html
The server expects data like so:
With $PSVersion.$PSVersion
equal to 3.0
and your exact input I get the following when I print the $influxdatajson
variable:
{
"name": "hd_used",
"columns": [
"value",
"host",
"mount"
],
"points": [
"23.2",
"serverA",
"mnt"
]
}
Which clearly isn't what you want but isn't what you said you got either.
The reason that that is the output we get is because your attempt to add the array to the existing array didn't work the way you expect because of powershell's annoying tendency to unroll arrays (I think).
If you work around that oddity by using this syntax instead:
$influxdata.points += ,@("23.2", "serverA", "mnt")
(the leading ,
forces an array context so that outer array gets unrolled instead of the array you are trying to add)
then I get the following output from $influxdatajson
:
{
"name": "hd_used",
"columns": [
"value",
"host",
"mount"
],
"points": [
[
"23.2",
"serverA",
"mnt"
]
]
}
Just to add my two pence worth. Its is worth noting that everytime you touch an array and you know is a single item array, you must use the appropriate comma syntax. This is not well highlighted in articles I found on the subject.
Take this example case I wrote for a Pester test case:
A lesson about single item arrays, every time you touch a single item array, you must use the comma op. It is not a case of set it and forget it:
Mock get-AnswerAdvancedFn -ModuleName Elizium.Loopz {
$pairs = @(, @('Author', 'Douglas Madcap Adams'));
$first = $pairs[0];
Write-Host "=== SINGLE-ITEM: pairs.count: $($pairs.Count), first.count: $($first.Count)"
([PSCustomObject]@{ Pairs = $pairs })
}
The above won't work, because of the fault assigning $pairs to Pairs even though we've used the correct syntax setting $pairs to @(, @('Author', 'Douglas Madcap Adams'))
The following fixes this issue; everytime you touch the single item array, you must use the comma syntax, otherwise you give PowerShell another chance to flatten your array:
Mock get-AnswerAdvancedFn -ModuleName Elizium.Loopz {
$pairs = @(, @('Author', 'Douglas Madcap Adams'));
$first = $pairs[0];
Write-Host "=== SINGLE-ITEM: pairs.count: $($pairs.Count), first.count: $($first.Count)"
([PSCustomObject]@{ Pairs = , $pairs })
}
My test code ended up being this:
Mock get-AnswerAdvancedFn -ModuleName Elizium.Loopz {
([PSCustomObject]@{ Pairs = , @(, @('Author', 'Douglas Madcap Adams')) })
}
Note, we had to use the comma op twice and both of those are necessary
To complement Etan Reisner's helpful answer (whose of use unary ,
to create a nested array solves the problem):
PowerShell's hashtable literals are quite flexible with respect to incorporating variable references, expression, and commands, which makes for a more readable solution:
,, [ordered] @{
name = 'hd_used'
columns = 'value', 'host', 'mount'
points = , (23.2, 'serverA', 'mnt')
} | ConvertTo-Json -Depth 3
This yields:
[
{
"name": "hd_used",
"columns": [
"value",
"host",
"mount"
],
"points": [
[
23.2,
"serverA",
"mnt"
]
]
}
]
Note how the array-construction operator (,
) is applied twice at the beginning of the pipeline (before [ordered]
):
Sending the result through the pipeline makes PowerShell unwrap any collection, i.e., enumerate the collection items and send them one by one, which in this case strips away the outer array, leaving ConvertTo-Json
to process the inner array, as desired.
Note that passing an array adds a level to the hierarchy, which is why the -Depth
value was increased to 3 above.
-Depth
is stringified (evaluated as if placed inside "$(...)"
), which in the case of an array would simply join the array elements with a space; e.g., array 23.2, 'serverA', 'mnt'
would turn to a single string with literal contents 23.2 serverA mnt
.Note how the arrays above do not use syntax @(...)
, because it is generally not necessary to construct arrays and is actually less efficient: simply ,
-enumerate the elements, and, if necessary, enclose in (...)
for precedence (although @()
is syntactically convenient for creating an empty array).
+
with an array as the LHS doesn't so much unwrap (unroll) its RHS, but concatenates arrays, or, to put it differently, allows you to append multiple individual items; e.g.:
$a = 1, 2
$a += 3, 4 # add elements 3 and 4 to array 1, 2 to form array 1, 2, 3, 4
Note that the use of +=
actually creates a new array behind the scenes, given that arrays aren't resizable.