A JMESPath cheat sheet for the CLI for Microsoft 365
JMESPath
The CLI documentation explains some of the basics of filtering. So for the common scenario’s like filtering on a Title it still I found the cases pretty straight forward. You can filter on any properties that are returned.
Yet for some other options I found it harder to find samples, especially if the CLI does return nested objects.
CLI for Microsoft 365 data
If you are working with CLI you get your data returned as JSON by
default. So you can test your queries live
at JMESPath.org using a response from the
CLI. Some simplified JSON for listing all sites using
the m365 spo site classic list --output json
would look as follows.
[{
"_ObjectType_": "Microsoft.Online.SharePoint.TenantAdministration.SiteProperties",
"AllowDownloadingNonWebViewableFiles": true,
"AllowEditing": false,
"Title": "Demo 1"
},
{
"_ObjectType_": "Microsoft.Online.SharePoint.TenantAdministration.SiteProperties",
"AllowDownloadingNonWebViewableFiles": false,
"AllowEditing": false,
"Title": "A Demo 2"
},
{
"_ObjectType_": "Microsoft.Online.SharePoint.TenantAdministration.SiteProperties",
"AllowDownloadingNonWebViewableFiles": true,
"AllowEditing": false,
"Title": "Sample 1"
}]
The most common queries are either to filter based on a specific
property, or use a contains, starts_with or ends_with
on a specific
property. The final scenario is to limit the return values to have a
smaller data set:
[?Title == 'Demo 1']
would return only the first item as it matches on the title Demo 1[?contains(Title, 'Demo')]
would return the first two items as it matches the Title on the word Demo[?contains(*, 'Demo 1')]
would return any item in the array where the value of any property would be Demo 1, currently only the first item.[?starts_with(Title, 'Demo')]
would only return the first item as it filters the title to start with Demo[?ends_with(Title, '1')]
returns the first and last item, as the title ends with a 1[?contains(Title, 'Demo') && AllowDownloadingNonWebViewableFiles]
returns only the first item as it combines two filters.[*].Title
returns only the Titles for all items.[*].{Title: Title}
returns all items as array with a Title property.
You can also use filters on sizing using comparison
operators [?value < 100]
. This can come in handy if you want to filter
out based on sizes.
For more complex scenario JMESPath can also help out. Besides filtering
you can use sorting options. Obviously you can sort your data set using
PowerShell or Bash. However in in some cases you might want to apply
the logic with JMESPath so it would work cross platform. As with the
previous sample, some dummy json
and you can test your queries.
[
{
"Report Refresh Date": "2021-06-15",
"User Principal Name": "garthf@contoso.com",
"Is Deleted": "False",
"Deleted Date": "",
"Last Activity Date": "2020-07-07",
"Viewed Or Edited File Count": "0",
"Synced File Count": "0",
"Shared Internally File Count": "0",
"Shared Externally File Count": "0",
"Visited Page Count": "0",
"Assigned Products": "OFFICE 365 E3",
"Report Period": "7"
},
{
"Report Refresh Date": "2021-06-15",
"User Principal Name": "sands@contoso.com",
"Is Deleted": "False",
"Deleted Date": "",
"Last Activity Date": "",
"Viewed Or Edited File Count": "152",
"Synced File Count": "0",
"Shared Internally File Count": "0",
"Shared Externally File Count": "0",
"Visited Page Count": "0",
"Assigned Products": "OFFICE 365 E3",
"Report Period": "7"
},
{
"Report Refresh Date": "2021-06-15",
"User Principal Name": "janets@contoso.com",
"Is Deleted": "True",
"Deleted Date": "2021-05-15",
"Last Activity Date": "",
"Viewed Or Edited File Count": "0",
"Synced File Count": "0",
"Shared Internally File Count": "0",
"Shared Externally File Count": "0",
"Visited Page Count": "0",
"Assigned Products": "OFFICE 365 E3",
"Report Period": "7"
}
]
sort_by(@, &"Last Activity Date")
would return the result set with the oldest Last Activity Date on top. That means empty dates first.reverse(sort_by(@, &"Last Activity Date"))
would reverse the order, shows the newest last activity date on top.reverse(sort_by(@, &"Viewed Or Edited File Count"))
would return the user with the most edited items on top.reverse(sort_by(@, &"Viewed Or Edited File Count"))[*]."User Principal Name
would sort and only return the User Principal Name sorted by the most edited files on top.reverse(sort_by(@, &"Viewed Or Edited File Count")) | [0]."User Principal Name"
would sort and return the User Principal Name for the user with the most edited files.reverse(sort_by(@, &"Viewed Or Edited File Count")) | [?"Is Deleted" == 'False']."User Principal Name"
sorts by then Viewed Or Edited File Count, then filters out deleted users and finally returns the User Principal Name
The last two commands show in the previous sample use a |
to pipe the
command. This allows you to further filter or tweak your set. Besides
using | [*]
to retrieve all results, or using | [0]
to get the first
item from the array you can also specify | [0:3]
to get the top 3
items.
You can also combine different options as sorting and selecting. So
given the previous data sample you can thus
use reverse(sort_by(@, &"Viewed Or Edited File Count")) | [0:3]."User Principal Name"
.
The query would sort and return the User Principal Name for top
three users with the most edited files.
Hope this cheat sheet helps you in case you are working with JMESPath queries and don’t hesitate to share your common scenario’s as well!
#SharingIsCaring