1

I need to create a singleton complex array. Background: I am trying to automate Let's Encrypt DNS challenge with GoDaddy. But the question is just about PS objects.

Suppose I have the following JSON object, which is my target notation

[
  {
    "data": "string",
    "port": 0,
    "priority": 0,
    "protocol": "string",
    "service": "string",
    "ttl": 0,
    "weight": 0
  }
]

I try to initialize the variable via Powershell as follows

$goDaddyDnsBody=@(
   @{
        "data"= $dnsChallenge;
        "port"= 1;
        "priority"= 0;
        "ttl"= 600;
        "weight"= 0    
    }
)

The above code is supposed to create an array containing only one item

But when I try to Write-Host ($goDaddyDnsBody |ConvertTo-Json) I get only the first element, not the whole array

{
  "weight": 0,
  "priority": 0,
  "data": ".................",
  "ttl": 600,
  "port": 1
}

The question is obvious: how can I make sure, without necessarily using string manipulation, that the object created is an array?

usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305
  • As an aside: [`Write-Host` is typically the wrong tool to use](http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/), unless the intent is to write _to the display only_, bypassing the success output stream and with it the ability to send output to other commands, capture it in a variable, or redirect it to a file. To output a value, use it _by itself_; e.g., `$value` instead of `Write-Host $value` (or use `Write-Output $value`, though that is rarely needed); see [this answer](https://stackoverflow.com/a/60534138/45375) – mklement0 Dec 21 '20 at 23:44

2 Answers2

2

Great work with the self answer!

I wanted to point out two things:

  1. the -AsArray parameter to ConvertTo-Json was not always available. It's in the current supported versions of PowerShell that are cross-platform. However, it is not available in Windows PowerShell (versions 5.1 and earlier) which many are still using.

  2. The original issue stems from using the pipeline with an array that contains a single object. Because the pipeline is "unrolling" the array and passing each object into the cmdlet, with a single object array the cmdlet only ever sees the single object. For more on that, see mklement0's excellent and detailed explanation in another answer.

You can instead produce an array by passing the array directly to the parameter:

ConvertTo-Json -InputObject @(@{a=1})

Result:

[
    {
        "a":  1
    }
]

Also worth noting that with the newer -AsArray option you don't need the wrapping array at all, in either the direct parameter or pipeline invocations:

ConvertTo-Json -InputObject @{a=1} -AsArray
@{a=1}|ConvertTo-Json -AsArray
briantist
  • 45,546
  • 6
  • 82
  • 127
1

I found the solution myself.

The problem is in with the serialization, not with the initialization of the singleton array. I just needed to add the following -AsArray switch

Write-Host ($goDaddyDnsBody |ConvertTo-Json -AsArray)

Sharing for posterity

usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305
  • 1
    Yes, but to add to [briantist's helpful answer](https://stackoverflow.com/a/65400727/45375): This isn't about _serialization_, but about _enumeration_, which the PowerShell pipeline performs by default; for the rationale behind this behavior, see [this answer](https://stackoverflow.com/a/60020105/45375). – mklement0 Dec 21 '20 at 23:50