0

I'm new to JSON and PowerShell. I'm wanting to receive a JSON object from AWS that indicates a server instance's status, and then read that status property programmatically so I can execute different logic based upon whether or not the instance is running.

Here's my PowerShell script:

$json = aws ec2 describe-instance-status --instance-id [instance ID redacted]
$outPath = 'C:\Scripts\results.json'
$json | ConvertTo-Json -depth 100 | Set-Content $outPath
$newJson = Get-Content $outPath -Raw | ConvertFrom-Json
echo $newJson.InstanceStatuses.InstanceStatus.Status

Here's the $json and $newJson to the console if I echo either of those out:

{
    "InstanceStatuses": [
        {
            "AvailabilityZone": "us-east-2c",
            "InstanceId": "[instance ID redacted]",
            "InstanceState": {
                "Code": 16,
                "Name": "running"
            },
            "InstanceStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            },
            "SystemStatus": {
                "Details": [
                    {
                        "Name": "reachability",
                        "Status": "passed"
                    }
                ],
                "Status": "ok"
            }
        }
    ]
}

However, if I try to access and echo out one of the properties (e.g. echo $newJson.InstanceStatuses.InstanceStatus.Status) I get nothing at the console. No error, no output, just a blank line.

If I try to access a property as an array (as hinted at in this SO answer), I get a cannot index into null array exception. I get the same exception if I try to treat the JSON as a dictionary and access properties by keys (as suggested in this SO answer).

I've reviewed the examples given in this SO question, this SO question, and this SO question in the course of (attempted) debugging, but have had no success.

Neil Wehneman
  • 154
  • 1
  • 12

2 Answers2

0

According to the AWS CLI doc, the command aws ec2 describe-instance-status --instance-id ... already yields a Json, from what we can see on your code, you are capturing that Json on your $json variable and then converting it again to Json to then export it to a file and then read it back. Lastly, attempting to convert it from Json to a PowerShell object, however as explained before this doesn't work because the output has been converted to Json 2 times.

The steps you should follow to get the status from your Json would be much simpler:

$json = aws ec2 describe-instance-status --instance-id [instance ID redacted]
$obj = $json | ConvertFrom-Json

With only that line you should already have an object which you can manipulate:

PS /> $obj.InstanceStatuses.InstanceStatus

Details                               Status
-------                               ------
{@{Name=reachability; Status=passed}} ok    

PS /> $obj.InstanceStatuses.InstanceStatus.Status
ok
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • I'm copying and pasting your code (with the instance-id filled in) and getting `ConvertFrom-Json : Invalid object passed in, ':' or '}' expected. (1): { At C:\scripts\json.ps1:1 char:78 + $json = aws ec2 describe-instance-status --instance-id [redacted] | Con ... + ~~~ + CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentEx ception + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Co mmands.ConvertFromJsonCommand` Any guidance on that? – Neil Wehneman Jan 18 '22 at 18:09
  • @NeilWehneman try wrapping the command with brackets `$json = (aws ec2 describe-instance......) | ConvertFrom-Json`, if that doesn't work, try using `Out-String` => `$json = aws ec2 describe-.... | Out-String | ConvertFrom-Json` – Santiago Squarzon Jan 18 '22 at 18:16
  • Wrapping the command gave the same error, just at char 80 instead of 78. The `Out-String` line produced error `Out-String : A positional parameter cannot be found that accepts argument '=>'. At line:1 char:1 + Out-String => $json = aws ec2 describe-instance-status --instance-id [redacted] ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~ + CategoryInfo : InvalidArgument: (:) [Out-String], ParameterBind ingException + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell .Commands.OutStringCommand` – Neil Wehneman Jan 18 '22 at 18:27
  • @NeilWehneman `Out-String =>` was to describe what you needed to do. The actual code is starting from the variable `$json = ....` – Santiago Squarzon Jan 18 '22 at 18:30
  • Oh, thanks for clarifying that. In that case the `Out-String`-based code produces the same `Invalid object passed in, ':' or '}' expected` error. – Neil Wehneman Jan 18 '22 at 18:37
  • @NeilWehneman what happens if you do the AWS call first, store it in a variable and then convert it from Json? See my last update – Santiago Squarzon Jan 18 '22 at 19:25
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241184/discussion-between-neil-wehneman-and-santiago-squarzon). – Neil Wehneman Jan 18 '22 at 20:14
0

I upgraded PowerShell from version 4.0 to version 5.1 by downloading the Windows Management Framework 5.1. After doing so, the various commands described in this post and its comments worked.

Note that my initial post contains a bug as pointed out by @SantiagoSquarzon. The following command sets all work:

$json = aws ec2 describe-instance-status --instance-id [instance ID redacted]
$json >> C:\scripts\aws1.json
$obj = Get-Content -Path C:\scripts\aws1.json | ConvertFrom-Json
echo $obj.InstanceStatuses.InstanceStatus.Status
$json = aws ec2 describe-instance-status --instance-id [instance ID redacted]
$json | Set-Content C:\scripts\aws2.json
$obj = Get-Content -Path C:\scripts\aws2.json | ConvertFrom-Json
echo $obj.InstanceStatuses.InstanceStatus.Status
$json = aws ec2 describe-instance-status --instance-id [instance ID redacted]
$obj = $json | ConvertFrom-Json
echo $obj.InstanceStatuses.InstanceStatus.Status
$json = (aws ec2 describe-instance-status --instance-id [instance ID redacted]) | ConvertFrom-Json
echo $json.InstanceStatuses.InstanceStatus.Status
$json = (aws ec2 describe-instance-status --instance-id [instance ID redacted]) | Out-String | ConvertFrom-Json
echo $json.InstanceStatuses.InstanceStatus.Status
Neil Wehneman
  • 154
  • 1
  • 12