skip to Main Content

I’m trying to access a specific field in a JSON object created by Azure Advisor using PowerShell. I have the following object:

@{id=/subscriptions/xxxx/providers/Microsoft.Advisor/recommendations/xxxx;
category=Cost;
impact=High;
impactedArea=Microsoft.Subscriptions/subscriptions;
description=Consider virtual machine reserved instance to save over your on-demand costs;
recommendationText=Consider virtual machine reserved instance to save over your on-demand costs;
recommendationTypeId=xxx; instanceName=xxxx;
additionalInfo=;
tags=;
ResourceId=/subscriptions/xxxx/providers/Microsoft.Advisor/recommendations/xxxx}

In this, I want to access a field ‘savingsCurrency’ to compare in an if-statement. The field is nested in ‘additionalInfo’, which in turn is in the ‘advisorRecommendation’ object.

I have the following code now:

Write-Output "advisorrecommendation: $advisorRecommendation"

if (-not([string]::IsNullOrEmpty($advisorRecommendation.additionalInfo)))
{
    $additionalInfo = $advisorRecommendation.additionalInfo | ConvertTo-Json
    Write-Output "additionalInfo: $additionalInfo"
    if (-not([string]::IsNullOrEmpty($additionalInfo.savingsCurrency)))
    {
        $savingsCurrency = $additionalInfo.savingsCurrency | ConvertTo-Json
        Write-Output "Currency: $savingsCurrency"
    }
}
else
{
    $additionalInfo = $null
}

This code gives me the following outputs:

advisorrecommendation:
@{id=/subscriptions/xxxx/providers/Microsoft.Advisor/recommendations/xxx; category=Cost; impact=High; impactedArea=Microsoft.Subscriptions/subscriptions; description=Consider virtual machine reserved instance to save over your on-demand costs; recommendationText=Consider virtual machine reserved instance to save over your on-demand costs; recommendationTypeId=xxxx; instanceName=xxxx; additionalInfo=; tags=; ResourceId=/subscriptions/xxxx/providers/Microsoft.Advisor/recommendations/xxxx}
additionalInfo: {
    "annualSavingsAmount": "697",
    "reservedResourceType": "virtualmachines",
    "targetResourceCount": "4",
    "savingsCurrency": "USD",
    "savingsAmount": "58",
    "lookbackPeriod": "30",
    "displaySKU": "Standard_B2s",
    "displayQty": "4",
    "location": "westeurope",
    "region": "westeurope",
    "vmSize": "Standard_B2s",
    "subId": "xxxx",
    "scope": "Single",
    "term": "P1Y",
    "qty": "4",
    "sku": "Standard_B2s"
}

The ‘savingsCurrency’ field never passes the null/empty check, even though I can clearly see that the field in ‘additionalInfo’ is not empty or null. What is going wrong here? If I try the print without the preceeding existence check, it simply prints the additionalInfo object with .savingsCurrency appended like this:

savingsCurrency: {
    "annualSavingsAmount": "697",
    "reservedResourceType": "virtualmachines",
    "targetResourceCount": "4",
    "savingsCurrency": "USD",
    "savingsAmount": "58",
    "lookbackPeriod": "30",
    "displaySKU": "Standard_B2s",
    "displayQty": "4",
    "location": "westeurope",
    "region": "westeurope",
    "vmSize": "Standard_B2s",
    "subId": "xxxx",
    "scope": "Single",
    "term": "P1Y",
    "qty": "4",
    "sku": "Standard_B2s"
}.savingsCurrency

2

Answers


  1. $advisorRecommendation.additionalInfo is an object with nested properties:

    $advisorRecommendation.additionalInfo.savingsCurrency
    # USD
    

    but $additionalInfo is a string because you’ve converted the object to json before assigning it:

    $additionalInfo = $advisorRecommendation.additionalInfo | ConvertTo-Json
    
    $additionalInfo.GetType().FullName
    # System.String
    

    As a result, $savingsCurrency = $additionalInfo.savingsCurrency is trying to read the savingsCurrency property of a string, and strings don’t have that property so you get $null.

    What you want to do instead is keep a reference to the $advisorRecommendation.additionalInfo object instead and only convert it to json for the purpose of writing it to the console:

    Write-Output "advisorrecommendation: $advisorRecommendation"
    
    #   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    if ($advisorRecommendation.additionalInfo -ne $null)
    #   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    {
    
        # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
        $additionalInfo = $advisorRecommendation.additionalInfo
        Write-Output "additionalInfo: $($additionalInfo | ConvertTo-Json -Depth 99)"
        # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
        if (-not([string]::IsNullOrEmpty($additionalInfo.savingsCurrency)))
        {
            $savingsCurrency = $additionalInfo.savingsCurrency
            Write-Output "Currency: $savingsCurrency"
        }
    }
    else
    {
        $additionalInfo = $null
    }
    

    You should now see Currency: USD in your output.

    Note that $additionalInfo.savingsCurrency is already a string so you don’t need to use ConvertTo-Json to display the value unless you specifically want it to be formatted as a json string (i.e. "USD" with surrounding quotes and any special characters like escaped, instead of the literal string value USD)

    Login or Signup to reply.
  2. The ‘savingsCurrency’ field never passes the null/empty check, even though I can clearly see that the field in ‘additionalInfo’ is not empty or null. What is going wrong here?

    You can check not null and if condition like below:

    $additionalInfo = $additionalInfo | ConvertFrom-Json
    if (-not([string]::IsNullOrEmpty($additionalInfo.savingsCurrency)))
        {
            $savingsCurrency = $additionalInfo.savingsCurrency | ConvertTo-Json
            Write-Output "Currency: $savingsCurrency"
        }
    

    enter image description here

    How to access JSON field in PowerShell

    To access any json filed you need to first convert it from json like below :

    $additionalInfo = $additionalInfo | ConvertFrom-Json
    $savingsCurrency= $savingsCurrency | ConvertFrom-Json
    

    To access any field you can use dot operator:

    $additionalInfo.savingsCurrency
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search