June 5th, 2018

Working with JSON data in PowerShell

Kory Thacher
Premier Field Engineer

Welcome back everyone! This week we will take another look at some common data types we might encounter in the real world: JSON data.

JSON data is used pretty frequently on the web if you’re hitting APIs. This not only includes external data (twitter, weather, marvel database), but often includes internal data to your company. It’s nice to be able to leverage data from anywhere, and it can be frustrating for people to try to parse JSON data.

Luckily, we have this all built in for you using ConvertFrom-JSON

I’ll get a response from an API online used for testing:

$response = Invoke-WebRequest -Uri '<a href="https://jsonplaceholder.typicode.com/users">https://jsonplaceholder.typicode.com/users</a>' -UseBasicParsing

The response data looks like this:

StatusCode : 200
StatusDescription : OK
Content : [
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwen...
RawContent : HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Origin, Accept-Encoding
Access-Control-Allow-Credentials: true
Pragma: no-cache
X-Content-Type-Options: nosniff
CF-Cache-...
Forms :
Headers : {[Transfer-Encoding, chunked], [Connection, keep-alive], [Vary, Origin, Accept-Encoding],
[Access-Control-Allow-Credentials, true]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml :
RawContentLength : 5645

And if we check out the “content” property we can see the actual JSON:

[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "Shanna@melissa.tv",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
},
{
"id": 3,
"name": "Clementine Bauch",
"username": "Samantha",
"email": "Nathan@yesenia.net",
"address": {
"street": "Douglas Extension",
"suite": "Suite 847",
"city": "McKenziehaven",
"zipcode": "59590-4157",
"geo": {
"lat": "-68.6102",
"lng": "-47.0653"
}
},
"phone": "1-463-123-4447",
"website": "ramiro.info",
"company": {
"name": "Romaguera-Jacobson",
"catchPhrase": "Face to face bifurcated interface",
"bs": "e-enable strategic applications"
}
},
{
"id": 4,
"name": "Patricia Lebsack",
"username": "Karianne",
"email": "Julianne.OConner@kory.org",
"address": {
"street": "Hoeger Mall",
"suite": "Apt. 692",
"city": "South Elvis",
"zipcode": "53919-4257",
"geo": {
"lat": "29.4572",
"lng": "-164.2990"
}
},
"phone": "493-170-9623 x156",
"website": "kale.biz",
"company": {
"name": "Robel-Corkery",
"catchPhrase": "Multi-tiered zero tolerance productivity",
"bs": "transition cutting-edge web services"
}
},
{
"id": 5,
"name": "Chelsey Dietrich",
"username": "Kamren",
"email": "Lucio_Hettinger@annie.ca",
"address": {
"street": "Skiles Walks",
"suite": "Suite 351",
"city": "Roscoeview",
"zipcode": "33263",
"geo": {
"lat": "-31.8129",
"lng": "62.5342"
}
},
"phone": "(254)954-1289",
"website": "demarco.info",
"company": {
"name": "Keebler LLC",
"catchPhrase": "User-centric fault-tolerant solution",
"bs": "revolutionize end-to-end systems"
}
},
{
"id": 6,
"name": "Mrs. Dennis Schulist",
"username": "Leopoldo_Corkery",
"email": "Karley_Dach@jasper.info",
"address": {
"street": "Norberto Crossing",
"suite": "Apt. 950",
"city": "South Christy",
"zipcode": "23505-1337",
"geo": {
"lat": "-71.4197",
"lng": "71.7478"
}
},
"phone": "1-477-935-8478 x6430",
"website": "ola.org",
"company": {
"name": "Considine-Lockman",
"catchPhrase": "Synchronised bottom-line interface",
"bs": "e-enable innovative applications"
}
},
{
"id": 7,
"name": "Kurtis Weissnat",
"username": "Elwyn.Skiles",
"email": "Telly.Hoeger@billy.biz",
"address": {
"street": "Rex Trail",
"suite": "Suite 280",
"city": "Howemouth",
"zipcode": "58804-1099",
"geo": {
"lat": "24.8918",
"lng": "21.8984"
}
},
"phone": "210.067.6132",
"website": "elvis.io",
"company": {
"name": "Johns Group",
"catchPhrase": "Configurable multimedia task-force",
"bs": "generate enterprise e-tailers"
}
},
{
"id": 8,
"name": "Nicholas Runolfsdottir V",
"username": "Maxime_Nienow",
"email": "Sherwood@rosamond.me",
"address": {
"street": "Ellsworth Summit",
"suite": "Suite 729",
"city": "Aliyaview",
"zipcode": "45169",
"geo": {
"lat": "-14.3990",
"lng": "-120.7677"
}
},
"phone": "586.493.6943 x140",
"website": "jacynthe.com",
"company": {
"name": "Abernathy Group",
"catchPhrase": "Implemented secondary concept",
"bs": "e-enable extensible e-tailers"
}
},
{
"id": 9,
"name": "Glenna Reichert",
"username": "Delphine",
"email": "Chaim_McDermott@dana.io",
"address": {
"street": "Dayna Park",
"suite": "Suite 449",
"city": "Bartholomebury",
"zipcode": "76495-3109",
"geo": {
"lat": "24.6463",
"lng": "-168.8889"
}
},
"phone": "(775)976-6794 x41206",
"website": "conrad.com",
"company": {
"name": "Yost and Sons",
"catchPhrase": "Switchable contextually-based project",
"bs": "aggregate real-time technologies"
}
},
{
"id": 10,
"name": "Clementina DuBuque",
"username": "Moriah.Stanton",
"email": "Rey.Padberg@karina.biz",
"address": {
"street": "Kattie Turnpike",
"suite": "Suite 198",
"city": "Lebsackbury",
"zipcode": "31428-2261",
"geo": {
"lat": "-38.2386",
"lng": "57.2232"
}
},
"phone": "024-648-3804",
"website": "ambrose.net",
"company": {
"name": "Hoeger LLC",
"catchPhrase": "Centralized empowering task-force",
"bs": "target end-to-end models"
}
}
]

This contains 10 fake users. If we want this data to be more usable we can parse the response directly using ConvertFrom-JSON:

$users = $response | ConvertFrom-Json

$users | FT

id name username email address
-- ---- -------- ----- -------
1 Leanne Graham Bret Sincere@april.biz @{street=Kulas Light; suite=Apt. 556; city=Gwenbo...
2 Ervin Howell Antonette Shanna@melissa.tv @{street=Victor Plains; suite=Suite 879; city=Wis...
3 Clementine Bauch Samantha Nathan@yesenia.net @{street=Douglas Extension; suite=Suite 847; city...
4 Patricia Lebsack Karianne Julianne.OConner@kory.org @{street=Hoeger Mall; suite=Apt. 692; city=South ...
5 Chelsey Dietrich Kamren Lucio_Hettinger@annie.ca @{street=Skiles Walks; suite=Suite 351; city=Rosc...
6 Mrs. Dennis Schulist Leopoldo_Corkery Karley_Dach@jasper.info @{street=Norberto Crossing; suite=Apt. 950; city=...
7 Kurtis Weissnat Elwyn.Skiles Telly.Hoeger@billy.biz @{street=Rex Trail; suite=Suite 280; city=Howemou...
8 Nicholas Runolfsdottir V Maxime_Nienow Sherwood@rosamond.me @{street=Ellsworth Summit; suite=Suite 729; city=...
9 Glenna Reichert Delphine Chaim_McDermott@dana.io @{street=Dayna Park; suite=Suite 449; city=Bartho...
10 Clementina DuBuque Moriah.Stanton Rey.Padberg@karina.biz @{street=Kattie Turnpike; suite=Suite 198; city=L...

Now we could do whatever we want with these users

foreach ($user in $users)

{

write-host "$($user.name) has the email: $($user.email)"

}
Leanne Graham has the email: Sincere@april.biz

Ervin Howell has the email: Shanna@melissa.tv

Clementine Bauch has the email: Nathan@yesenia.net

Patricia Lebsack has the email: Julianne.OConner@kory.org

Chelsey Dietrich has the email: Lucio_Hettinger@annie.ca

Mrs. Dennis Schulist has the email: Karley_Dach@jasper.info

Kurtis Weissnat has the email: Telly.Hoeger@billy.biz

Nicholas Runolfsdottir V has the email: Sherwood@rosamond.me

Glenna Reichert has the email: Chaim_McDermott@dana.io

Clementina DuBuque has the email: Rey.Padberg@karina.biz

So there you have it, working with JSON data can be easy once you turn it into PowerShell objects. Hopefully this helps you work with APIs and process data on your PowerShell adventures.

If you like the content don’t forget to rate, comment and share!

Author

Kory Thacher
Premier Field Engineer

I've been a PFE since 2012, working with various technologies. I live in the modern applications domain, doing work in UWP apps, .NET, Unity, DevOps, and of course PowerShell. I've been teaching PowerShell related workshops very frequently for years, and I really enjoy getting the opportunity to explain a topic or learn something new from my colleagues. I enjoy scripting because of how fast and interactive it can be, and I love getting interesting problems to work on with customers. ...

More about author

1 comment

Discussion is closed. Login to edit/delete existing comments.

  • Paul Watson

    The first request did not work for me as it contains XML code. This worked.

    $response = Invoke-WebRequest -Uri 'https://jsonplaceholder.typicode.com/users' -UseBasicParsing

    Please show how to do something with the ‘address’ member.