Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Loop Through JSON File in PowerShell

Tags: json key object

Using ConvertFrom-Json Cmdlet

We can use the ConvertFrom-Json cmdlet to traverse the JSON file with first and nested-level keys; Let’s explore them below.

Traverse JSON File Containing First-Level Keys

Use ConvertFrom-Json with the foreach loop to traverse the JSON file having first-level keys only.

{
    "name": "John Christoper",
    "age": 40,
    "city": "Washington"
}
$jsonData = Get-Content -Path "./file.json" -Raw | ConvertFrom-Json
foreach ($current_property in $jsonData.PSObject.Properties) {
    Write-Host "$($current_property.Name): $($current_property.Value)"
}
name: John Christoper
age: 40
city: Washington

We used the Get-Content cmdlet to read the contents of a JSON file located at ./file.json path, which we specified using the -Path parameter. The -Raw parameter ensured the file’s entire content was read as a single string before passing to the ConvertFrom-Json cmdlet.

We used the ConvertFrom-Json cmdlet to convert the JSON string into a PowerShell Object (PSObject), which we stored in the $jsonData variable. Then, we used the for loop to iterate over all properties in the $jsonData.

How did we retrieve all properties? This expression $json.PSObject.Properties retrieved the properties of the $jsonData object as a collection.

For each property ($current_property), we used $current_property.Name and $current_property.Value to retrieve the current property name and its corresponding value, respectively.

After that, we constructed a string by combining the property name and its value as "$($current_property.Name): $($current_property.Value)" to further display on the PowerShell console using the Write-Host cmdlet.

Let’s take another example, but we will take the key from the user this time; see the following example.

{
    "name": "John Christoper",
    "age": 40,
    "city": "Washington"
}
$jsonData = Get-Content -Path "./file.json" -Raw | ConvertFrom-Json
$key = Read-Host -Prompt "Enter key"

foreach ($record in $jsonData) {
   if ($record |
       Select-Object -ExpandProperty $key -ErrorAction SilentlyContinue){
           Write-Host "$($record.$key)"
    }else{
           Write-Host "The given key was not found."
    }
}
Enter key: name
John Christopher
Enter key: random
The given key was not found.

Again, we used the Get-Content and ConvertFrom-Json to read the JSON file’s content and assign it to the $jsonData variable. After that, we used the Read-Host cmdlet with the -Prompt parameter to prompt the user and enter the desired key. We stored this key in the $key variable.

Next, we used the foreach loop (a.k.a. foreach statement) to iterate over the $jsonData. In each iteration, we piped the $record to the Select-Object cmdlet with the -ExpandProperty parameter to select and expand the property given by the $key.

We set the -ErrorAction to the SilentlyContinue to suppress the error message because we wanted to show our custom message rather than the error generated by the PowerShell.

So, if the $key was present in the JSON file, the Write-Host cmdlet from the if block would be executed to print the corresponding value; otherwise, the else block would be executed to display a message on the console saying the given know not found.

Let’s dive deeper and work with the JSON file with nested keys.

Traverse JSON File Containing First-Level Keys

Use ConvertFrom-Json with the foreach loop to traverse the JSON file having nested keys.

{
    "student1": {
        "name": {
            "firstName": "John",
            "lastName": "Doe"
        },
        "age": 30,
        "Courses": {
            "CS123": "Introduction to Computer Science",
            "DS234": "Introduction to DataScience"
        }
    },
    "student2": {
        "name": {
            "firstName": "Thomas",
            "lastName": "Nelsan"
        },
        "age": 28,
        "Courses": {
            "CS123": "Java Programming",
            "Ph234": "Introduction to Psychology"
        }
    }
}
#Define a function named TraverseJson that takes a JSON object ($json)
#and an optional prefix ($prefix)
function TraverseJson($json, $prefix = '') {

    # Iterate over each property in the JSON object
    foreach ($property in $json.PSObject.Properties) {

        # Get the name and value of the property
        $propertyName = $property.Name
        $propertyValue = $property.Value

        # Check if the property value is a nested object
        if ($propertyValue -is [System.Management.Automation.PSCustomObject]) {

            # Check if it's the first level of keys
            if ($prefix -eq '') {
                # Display the available first-level keys
                Write-Host "First level keys:"
                foreach ($firstLevelKey in $json.PSObject.Properties.Name) {
                    Write-Host "- $firstLevelKey"
                }

                # Prompt the user to choose a first-level key
                $firstLevelKey = Read-Host "Choose a first level key (enter 'exit' to exit)"

                # If 'exit' is entered, return and exit the recursion
                if ($firstLevelKey -eq "exit") {
                    return
                }

                # If the chosen first-level key is valid
                elseif ($json.PSObject.Properties.Name -contains $firstLevelKey) {
                    # Get the available second-level keys for the chosen first-level key
                    $secondLevelKeys = $json.$firstLevelKey.PSObject.Properties.Name
                    Write-Host "Second level keys under '$firstLevelKey':"
                    foreach ($secondLevelKey in $secondLevelKeys) {
                        Write-Host "- $secondLevelKey"
                    }

                    # Prompt the user to choose a second-level key
                    $secondLevelKey = Read-Host "Choose a second level key (enter 'exit' to exit)"

                    # If 'exit' is entered, return and exit the recursion
                    if ($secondLevelKey -eq "exit") {
                        return
                    }

                    # If the chosen second-level key is valid
                    elseif ($secondLevelKeys -contains $secondLevelKey) {
                        # Get the nested value corresponding to the chosen keys
                        $nestedValue = $json.$firstLevelKey.$secondLevelKey
                        Write-Host "Value of '$firstLevelKey.$secondLevelKey': $nestedValue"
                    }

                    else {
                        Write-Host "Invalid second level key. Please try again."
                    }

                    # Recursively call the TraverseJson function with the
                    #nested value and an updated prefix
                    TraverseJson $json.$firstLevelKey.$secondLevelKey ($firstLevelKey + '.' + $secondLevelKey + '.')
                }
                else {
                    Write-Host "Invalid first level key. Please try again."
                }

                # Return to exit the recursion
                return
            }

            # If it's not the first level of keys
            else {
                # Recursively call the TraverseJson function with the
                #nested object and an updated prefix
                TraverseJson $propertyValue ($prefix + $propertyName + '.')
            }
        }

        # If the property value is an ArrayList
        elseif ($propertyValue -is [System.Collections.ArrayList]) {
            # Iterate over each item in the ArrayList
            $index = 0
            foreach ($item in $propertyValue) {
                #Recursively call the TraverseJson function with the item
                #and an updated prefix, including the array index
                TraverseJson $item ($prefix + $propertyName + "[$index].")
                $index++
            }
        }

        # If it's a regular property (not a nested object or ArrayList)
        else {
            # Display the key and value
            Write-Host "${prefix}${propertyName}: ${propertyValue}"
        }
    }
}

#Read the content of the JSON file and convert it to a JSON object
$json = Get-Content -Path "./file.json" -Raw | ConvertFrom-Json

#Call the TraverseJson function with the JSON object
TraverseJson $json
First level keys:
- student1
- student2
Choose a first level key from the options above (or enter 'exit' to exit): student1
Second level keys under 'student1':
- name
- age
- Courses
Choose a second level key from the options above (or enter 'exit' to exit): age
Value of 'student1.age': 30
First level keys:
- student1
- student2
Choose a first level key from the options above (or enter 'exit' to exit): student2
Second level keys under 'student2':
- name
- age
- Courses
Choose a second level key from the options above (or enter 'exit' to exit): Courses
Value of 'student2.Courses': @{CS123=Java Programming; Ph234=Introduction to Psychology}
student2.Courses.CS123: Java Programming
student2.Courses.Ph234: Introduction to Psychology

Don’t be afraid to look at the code; it is very simple and straightforward; Let’s learn it step by step below:

  • First, we defined the TraverseJson function, which took two parameters: $json represented the JSON object, and $prefiex stored the prefix for nested keys. This function recursively traversed the JSON object and displayed the key-value pairs.
  • The TraverseJson function began with the foreach loop, which iterated over the properties of the $json object using $json.PSObject.Properties.
  • Inside the foreach loop, the name and value for every property are assigned to the $propertyName and $propertyValue variables, respectively.
  • Then, the above code checked if the $propertyValue was a nested object using the -is operator and the type [System.Management.Automation.PSCustomObject]. If it was, the code entered the if block.
  • There was an additional check for the $prefix variable within the if block. We were at the first level of keys if it was an empty string. In this case, the code displayed the available first-level keys by iterating over $json.PSObject.Properties.Name and prompted the user to choose a first-level key.
  • If the user entered exit, the function returned and exited the recursion. Otherwise, if the chosen first-level key was valid ($json.PSObject.Properties.Name -contains $firstLevelKey), the code displayed the available second-level keys for the chosen first-level key.
  • The second-level keys were obtained from $json.$firstLevelKey.PSObject.Properties.Name and displayed to the user.
  • The user was prompted to choose a second-level key. If exit was entered, the function returned and exited the recursion. If the chosen second-level key was valid ($secondLevelKeys -contains $secondLevelKey), the code retrieved the corresponding nested value using $json.$firstLevelKey.$secondLevelKey and displayed it.
  • If the chosen second-level key was invalid, an error message was displayed, and the user was prompted to try again.
  • Finally, the TraverseJson function called itself recursively with the selected nested value ($json.$firstLevelKey.$secondLevelKey) and an updated prefix ($firstLevelKey + '.' + $secondLevelKey + '.').
  • If the $prefix was not empty (indicating nested keys), the function recursively called TraverseJson on the nested object ($propertyValue) with an updated prefix ($prefix + $propertyName + '.').
  • If the $propertyValue was an ArrayList, the code entered an elseif block and iterated over each item in the ArrayList using a foreach loop. It recursively called TraverseJson on every item with an updated prefix that included the array index.
  • If the $propertyValue was neither a nested object nor an ArrayList, it entered the else block and displayed the full key path along with the corresponding value using the Write-Host cmdlet.
  • Finally, outside the function, the code read the JSON file content using the Get-Content cmdlet, converted it to a JSON object using ConvertFrom-Json, and called the TraverseJson function with the JSON object.

So, the above code allowed the user to interactively traverse a JSON object, select keys at different levels, and view their corresponding values. This code is limited to second-level keys; you can add value to it to fit your requirements.

What is the importance of using ConvertFrom-Json, which compels us to use it in every above solution? Because PowerShell can’t iterate over the JSON objects directly, we used the ConvertFrom-Json to convert the JSON string to a PSCustomObject, where each property represents a JSON field.

The above solutions will work if you use PowerShell version 3.0+; run the $PSVersionTable.PSVersion to check your PowerShell version. If you are using PowerShell version 2.0 or looking for an alternative, the following solution is for you.

Using JavaScriptSerializer Class

Use the JavaScriptSerializer class to loop through the JSON if you are using PowerShell version 2.0.

Add-Type -AssemblyName System.Web.Extensions
$JS = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$json = @'
[{"id":1,"firstName":"John","lastName":"Doe","age":32},
{"id":2,"firstName":"Thomas","lastName":"Christoper","age":30},{"id":3,"firstName":"Johny","lastName":"Daniel","age":29}]
'@
$data = $JS.DeserializeObject($json)
$data.GetEnumerator() | foreach-Object {
    foreach ($key in $_.Keys){
        Write-Host "$key : $($_[$key])"
    }
}
id : 1
firstName : John
lastName : Doe
age : 32
id : 2
firstName : Thomas
lastName : Christoper
age : 30
id : 3
firstName : Johny
lastName : Daniel
age : 29

First, we used the Add-Type command to load the System.Web.Extensions assembly into the current session. This assembly provides classes for working with JSON data in .NET applications.

Then, we used the New-Object cmdlet to create an object of the JavaScriptSerializer class from the System.Web.Script.Serialization namespace, which we stored in the $JS variable.

After that, we used the DeserializeObject() method of the $JS object. This method took JSON string ($json) as a parameter to deserialize it into the PowerShell object. We stored the resulting object in the $data variable.

Next, we loop through each item in the $data using the GetEnumerator() method and foreach-Object cmdlet. Inside the foreach-Object, we used the foreach loop with the Keys property of the current item to iterate over each key in the current item. We displayed the corresponding key-value pair using the Write-Host cmdlet.

That’s all about how to Loop through JSON File in PowerShell.



This post first appeared on How To Learn Java Programming, please read the originial post: here

Share the post

Loop Through JSON File in PowerShell

×

Subscribe to How To Learn Java Programming

Get updates delivered right to your inbox!

Thank you for your subscription

×