1

Given this JSON

{"name":"//iam.googleapis.com/projects/aw-b9a-8231-4086-a297-ca0/serviceAccounts/1081069135974252","asset_type":"iam.googleapis.com/ServiceAccount","resource":{"version":"v1","discovery_document_uri":"https://iam.googleapis.com/$discovery/rest","discovery_name":"ServiceAccount","parent":"//cloudresourcemanager.googleapis.com/projects/1090951556423","data":{"email":"default@aw-d1eb6b9a-8231-4086-a297-ca0.iam.gserviceaccount.com","name":"projects/aw-d1eb6b9a-8231-4086-a297-ca0/serviceAccounts/default@aw-d1eb6b9a-8231-4086-a297-ca0.iam.gserviceaccount.com","oauth2ClientId":"108102635374252","projectId":"aw-d1eb6b9a-8231-4086-a297-ca0","uniqueId":"108108526913531974252"}},"ancestors":["projects/1090951556423","folders/940897400840","folders/140924730741","organizations/437515948226"],"update_time":"2021-02-08T18:23:18Z"}

I'm trying to use the following snippet from Windows command window,

powershell -nologo -executionpolicy bypass "& {foreach($line in Get-Content temp.txt) {ConvertFrom-Json -InputObject $line}}" > temp2.txt

To get the retrieved keys and values into a file (temp2.txt). However, ConvertFrom-Json only gets the first hierarchic level of the JSON, now down in the data array. I have tried -Depth 3 but get this error:

At line:1 char:81
+ ... ontent temp.txt) {ConvertFrom-Json  -InputObject $line -Depth 4 -Comp ...
+                                                            ~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [ConvertFrom-Json], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.ConvertFromJsonCommand```

Dave
  • 378
  • 4
  • 14
  • 2
    The `-Depth` parameter is only available in PS Core (6.2 and up), not earlier versions of PowerShell. Having said that, PowerShell 5.1 on my machine decodes everything correctly without having to specify more depth. If you only need what's in `data` you should just drill into the object: `(ConvertFrom-Json ...).resource.data`. – Jeroen Mostert Aug 16 '21 at 16:16

1 Answers1

4

As Jeroen Mostert points out in a comment, only in PowerShell (Core) v6.2+ does ConvertFrom-Json have a -Depth parameter. However, even if it were available to you, it would neither be needed nor would it help, because ConvertFrom-Json correctly parses JSON with a nesting depth up to 1024 levels by default.

  • In other words: ConvertFrom-Json -Depth $someDepth is only needed in the unlikely event that your JSON has more than 1024 levels or if you want to ensure that input JSON does not exceed a given nesting depth (because exceeding it results in an error - unlike how -Depth works with the complementary cmdlet, ConvertTo-Json - see this post).

Your problem stems from the fact that >, PowerShell's redirection operator is in effect an alias of Out-File, which, when given complex objects as input, saves them using the same for-display representation you would see in the console - and with a deeply nested input object such as yours the resulting interpretation can be unhelpful (since your input object has more than 4 top-level properties, it is implicitly formatted with Format-List).

  • Note: You're actually using cmd.exe's > operator, but the above still applies, because the same kind of formatting is also applied when PowerShell outputs to an outside caller's stdout.

So the question for you to decide is:

  • What representation are you looking for to be saved in file temp2.txt?

  • Are you looking for a for-display representation - for the human observer - or a format suitable for later programmatic processing?

If you're primarily looking to pretty-print the input JSON, you can use a ConvertFrom-Json / ConvertTo-Json round-trip operation, whose output will be pretty-printed by default:

powershell -executionpolicy bypass -c "ConvertFrom-Json (Get-Content -Raw temp.txt) | ConvertTo-Json" > temp2.txt

Note:

  • As hinted at above, with ConvertTo-Json, i.e. the re-conversion to JSON, -Depth (available also in Windows PowerShell) is much more likely to be required (though not with your particular input object), because the default depth is only 2, and exceeding it results in quiet truncation (up to PowerShell 7.0; since v7.1, at least a warning is issued) - again, see this post.

  • I've streamlined incidental aspects of your call to powershell.exe, the Windows PowerShell CLI call - for a comprehensive overview of the CLI in both PowerShell editions, see this answer.

  • You may run into character-encoding issues with non-ASCII characters, given that cmd.exe uses the system's active OEM code page. Saving to a file from inside the PowerShell command can give you control over the desired encoding.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Done! Jeroen's part of the answer helped although it wasn't quite the same question. I struggle with Powershell as a newbie, it's good stuff but hard to put the pieces together (as opposed say Javascript which is much more intuitive at least to me). I have a head for wierd code though, in my defense I know LOTS about XSLT for example. :-) – Dave Aug 16 '21 at 23:25
  • 1
    Thanks, @Dave. Yes, PowerShell takes some getting used to, but it's worth putting in the time to understand its fundamentals, as it will make you much more productive. (Unfortunately, PowerShell's commitment to backward-compatibility has also resulted in quite a few historical warts being part of the package). – mklement0 Aug 16 '21 at 23:29