Using PowerShell for dynamic JSON parsing

September 3, 2012

in JSON,Microsoft,PowerShell,PowerShell V3

With the release of PowerShell v3, working with JSON has become simple. After reading Rick Strahl’s post Using JSON.NET for dynamic JSON parsing I thought it’d be great to work up some of those examples in PowerShell.

Check out what else you can do in PowerShell v3 here and here.

Creating JSON on the fly with ConvertTo-JSON

Here is one simple way of creating JSON on the fly in PowerShell. I want to dial in on a couple of new PowerShell v3 features here.

First, I’m casting the hash table with [ordered] so the the keys will be in the order I add them.  Casting  to [ordered] creates an OrderedDictionary instead of HashTable.

Once I finish building up the ordered dictionary I pipe it to ConvertTo-Json, which, convers it to a JSON formatted string.

I need to set the depth to 3 with the –Depth parameter because the default is 2 levels of contained objects and my resulting structure has 3. The $jsonObject, $album and then $songs.

$jsonObject = [ordered]@{}            
            
$jsonObject.Entered = (Get-Date).DateTime            
            
$album = @{}            
$album.AlbumName = "Dirty Deeds Done Dirt Cheap"            
$album.Artist = "AC/DC"            
$album.YearReleased = 1976            
            
$album.Songs = @()            
                        
$song = @{}            
$song.SongName = "Dirty Deeds Done Dirt Cheap"            
$song.SongLength = "4:11"            
$album.Songs += $song            
            
$song = @{}            
$song.SongName = "Love at First Feel"            
$song.SongLength = "3:10"            
$album.Songs += $song            
            
$jsonObject.album = $album            
            
$jsonObject | ConvertTo-Json -Depth 3

Here is the resulting JSON.


{
"Entered":  "Saturday, September 01, 2012 10:30:04 AM",
"album":  
    {
        "Artist":  "AC/DC",
        "AlbumName":  "Dirty Deeds Done Dirt Cheap",
        "Songs":  [
                    {
                        "SongName":  "Dirty Deeds Done Dirt Cheap",
                        "SongLength":  "4:11"
                    },
                    {
                        "SongName":  "Love at First Feel",
                        "SongLength":  "3:10"
                    }
                ],
        "YearReleased":  1976
    }
}

Creating a PowerShell Object from JSON with ConvertFrom-JSON

Going the other way, this PowerShell snippet sets up a JSON string with three properties: Name, Company and Entered. Piping the string to ConvertFrom-Json creates a PowerShell object with these three properties.

$jsonString = @'
{
    "Name":"John",
    "Company":"Microsoft",
    "Entered":"2012-03-16T00:03:33.245-10:00"
}
'@            
            
$jsonString | ConvertFrom-Json

The resulting PowerShell object displayed.

Name Company   Entered                      
---- -------   -------                      
John Microsoft 2012-03-16T00:03:33.245-10:00

Complex JSON

Let’s take a look at a chewier JSON structure (see below the JSON string). From the string you can directly navigate to the objects, properties and elements of the arrays.

Notice here I’m using the new PowerShell v3 Member Enumeration feature. That’s why the two dates, 1976 and 1992 are printed from the single line $albums.YearReleased.

$albums = $jsonString | ConvertFrom-Json             
            
$albums.YearReleased            
            
$albums[0].AlbumName            
$albums[0].Songs[1].SongName

Result navigating Complex JSON

Here is what you get from running the previous script.

1976
1992
Dirty Deeds Done Dirt Cheap
Love at First Feel

JSON String

This is the JSON string used in the previous example.

$jsonString = [
{
"Id": "b3ec4e5c",
"AlbumName": "Dirty Deeds Done Dirt Cheap",
"Artist": "AC/DC",
"YearReleased": 1976,
"Entered": "2012-03-16T00:13:12.2810521-10:00",
"AlbumImageUrl": "http://ecx.images-amazon.com/images/I/61kTaH-uZBL._AA115_.jpg",
"AmazonUrl": "http://www.amazon.com/gp/product/…ASIN=B00008BXJ4",
"Songs": [
    {
    "AlbumId": "b3ec4e5c",
    "SongName": "Dirty Deeds Done Dirt Cheap",
    "SongLength": "4:11"
    },
    {
    "AlbumId": "b3ec4e5c",
    "SongName": "Love at First Feel",
    "SongLength": "3:10"
    },
    {
    "AlbumId": "b3ec4e5c",
    "SongName": "Big Balls",
    "SongLength": "2:38"
    }
]
},
{
"Id": "7b919432",
"AlbumName": "End of the Silence",
"Artist": "Henry Rollins Band",
"YearReleased": 1992,
"Entered": "2012-03-16T00:13:12.2800521-10:00",
"AlbumImageUrl": "http://ecx.images-amazon.com/images/I/51FO3rb1tuL._SL160_AA160_.jpg",
"AmazonUrl": "http://www.amazon.com/End-Silence-Rollins-Band/dp/B0000040OX/ref=sr_1_5?ie=UTF8&qid=1302232195&sr=8-5",
"Songs": [
    {
    "AlbumId": "7b919432",
    "SongName": "Low Self Opinion",
    "SongLength": "5:24"
    },
    {
    "AlbumId": "7b919432",
    "SongName": "Grip",
    "SongLength": "4:51"
    }
]
}]

Let’s Put some JSON on a Web endpoint

Using Invoke-RestMethod you can send PowerShell objects that have been converted to JSON to a web endpoint. I’m using the freely hosted HTTP Request & Response Service, http://httpbin.org.

I get the first two processes from Get-Process and convert them to JSON.  Then I add that JSON result to the overall payload and finally call Invoke-RestMethod which “puts” it to the web endpoint.

$p = Get-Process | Select -First 2 Name, Company, PM |             
        ConvertTo-Json            
            
$jsonString = "[{Date=$(Get-Date), Processes=$($p)}]"            
            
$body = $jsonString | ConvertTo-Json            
            
Invoke-RestMethod -Method Put http://httpbin.org/put -Body $body

Web Endpoint Results

We can see from the json properties that the values were transmitted correctly.

origin  : 68.174.133.109
files   : 
form    : 
url     : http://httpbin.org/put
args    : 
headers : @{Content-Length=302; Host=httpbin.org; Content-Type=; Connection=keep-alive; User-Agent=Mozilla/5.0 (Windows NT; Windows NT 6.1; en-US) 
          WindowsPowerShell/3.0}
json    : [{Date=09/02/2012 15:23:26, Processes=[
              {
                  "Name":  "armsvc",
                  "Company":  "Adobe Systems Incorporated",
                  "PM":  1249280
              },
              {
                  "Name":  "atieclxx",
                  "Company":  "AMD",
                  "PM":  2473984
              }
          ]}]
data    : "[{Date=09/02/2012 15:23:26, Processes=[\r\n    {\r\n        \"Name\":  \"armsvc\",\r\n        \"Company\":  \"Adobe Systems 
          Incorporated\",\r\n        \"PM\":  1249280\r\n    },\r\n    {\r\n        \"Name\":  \"atieclxx\",\r\n        \"Company\":  \"AMD\",\r\n       
           \"PM\":  2473984\r\n    }\r\n]}]"

{ 1 trackback }

JSON is very nearly valid PowerShell
09.16.12 at 5:12 pm

{ 4 comments… read them below or add one }

Jim 11.04.12 at 9:51 pm

Please, please, PLEASE give us an out-of-the-box way to make PowerShell an HTTP listener. Do you have any idea how many hours of internal tier-3 support calls could be eliminated if we could provide simple, web-enabled, powershell scripts to Help Desk personnel? I understand things like forms input validation and so forth would still need to be done. PowerShell can do that!

But what it CANNOT do at the moment (at least not easily) is listen to a POST from a web page. We’re 98% there.

Doug Finke 11.05.12 at 10:36 am

Thanks for the comment Jim. I totally agree.

Check this out. Food for thought at least.
Guide for Windows PowerShell Web Access

Chris Magnuson 02.23.13 at 6:46 pm

@Jim, what you want is possible today with PowerShell pipeworks. I have it configured with a VM called powershell and can now quickly turn powershell commands into webpages that can be utilized by others in the company.

Check out the best information available at the links below:

http://powershellpipeworks.com/
http://powershellpipeworks.com/Module.ashx

This is by no means for the feint of heart, it felt like I had to experimentally determine how much of the parameters worked and reverse engineer how to do things like get query string parameters but it is all there if you have the ability to figure it out.

I am working on a blog post (probably series) that details how to do this for yourself as the current documentation is abysmal and information on the web about this hidden jem is sparse to say the least.

Doug Finke 02.25.13 at 2:07 pm

Thanks for the comment Chris.

I looked at your blog, good stuff. I don’t see a way to get in contact with you.

Let me know how to.

Thanks
Doug

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Contrat Creative Commons

© 2007-2013, Doug Finke