2

I have this function

function Get-JsonContent{
  param (
    [Parameter(
      Mandatory = $true,
      HelpMessage = "Path to the json config file."
    )]
    [string] $Filepath
  )
  $content = Get-Content -Path $Filepath -Raw
  $config = $content | ConvertFrom-Json -NoEnumerate
  return $config

}

That basically just reads the json, I noticed that single element json arrays get converted into an object, and this can be solved by using the -NoEnumerate parameter at least from powershell seven. By doing this however I only notice this works when I pipe the ConvertFrom-Json with Convert-ToJson

So for example

ConvertFrom-Json $var -NoEnumerate | ConvertTo-Json

However the below implementation doesn't work I for example read two json files, merge the files the convert the output to json, so not entirely sure how that would work.I could use the -Array option but I also have other objects I don't want to convert to arrays

2
  • remove the assignment $config = just return from $content | ConvertFrom-Json -NoEnumerate and it should preserve the array. Compare: & { $a = '[{"foo": "bar"}]' | ConvertFrom-Json -NoEnumerate; $a } | ConvertTo-Json versus & { '[{"foo": "bar"}]' | ConvertFrom-Json -NoEnumerate } | ConvertTo-Json Commented Mar 10 at 19:08
  • Try using the Comma operator ,, meaning: return ,$config Commented Mar 11 at 9:07

1 Answer 1

3

Think that every object outputted from a script block, function or cmdlet is enumerated, and due to this, if the object being enumerated happens to be a single element array then PowerShell dynamically assigns it as a scalar value. The -NoEnumerate parameter prevents this enumeration from happening, however this only works once, when the cmdlet outputs. In your case, you have a variable assignment from the cmdlet, the array is preserved up until this point, but then when you use that variable as output the enumeration isn't prevented. The about_Pipelines documentation is probably the one that goes more in depth with this and also explains why this enumeration behavior is required.

Perhaps this simple example helps you visualize it, Write-Output -NoEnumerate can help us emulate what is happening in your case:

# the array is enumerated and assigned as a scalar
$config = & { @(1) }
$config.GetType() # Type: int

# `-NoEnumerate` prevents the script block enumeration
$config = & { Write-Output @(1) -NoEnumerate }
$config.GetType() # Type: object[] 

# the use of the variable assignment enumerates the value
$config = & { $config = Write-Output @(1) -NoEnumerate; $config }
$config.GetType() # Type: int

So, by simply removing the assignment the issue should be solved:

function Get-JsonContent {
    param (
        [Parameter(
            Mandatory = $true,
            HelpMessage = 'Path to the json config file.'
        )]
        [string] $Filepath
    )

    Get-Content -Path $Filepath -Raw | ConvertFrom-Json -NoEnumerate
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.