Powershell JSON Building - json

I am having problems getting assembling this Json in Powershell
{
"totalCount": 1,
"list": [
{
"type": "ToggleLightingState",
"order": 1,
"delay": null,
"postDelay": null,
"name": "Toggle lighting state of light L-17E-611-KB-1",
"parameters": {
"relayIds": [],
"curveType": null,
"behavior": null,
"duration": null,
"useAssignedSpace": false,
"spaceIds": [],
"lightIds": [
2408
],
"spaceGroupIds": []
}
}
]
}
I am Iterating through an array using a for loop to fill in the values. I am just struggling to generate a list inside a list in JSON
$ActionList = #{
#(
#{
type = 'ToggleLightingState'
order = 1
delay = 'null'
postDelay = 'null'
name = $actionSets[$i][0]
}
)
}
ConvertTo-Json -InputObject $ActionList

You don't have the name of the array "list" inside the object. It looks like you can't have an unnamed array inside an object. I don't know what $actionsets is, so I took off the indexes. Plus fixing your syntax errors results in the below. Note that 'null' and $null are different things.
$ActionList = #{
list = #(
#{
type = 'ToggleLightingState'
order = 1
delay = 'null'
postDelay = 'null'
name = $actionSets
}
)
}
ConvertTo-Json -InputObject $ActionList
{
"list": [
{
"delay": "null",
"name": null,
"postDelay": "null",
"type": "ToggleLightingState",
"order": 1
}
]
}

Using this ConvertTo-Expression cmdlet:
$Json = #'
{
"totalCount": 1,
"list": [
{
"type": "ToggleLightingState",
"order": 1,
"delay": null,
"postDelay": null,
"name": "Toggle lighting state of light L-17E-611-KB-1",
"parameters": {
"relayIds": [],
"curveType": null,
"behavior": null,
"duration": null,
"useAssignedSpace": false,
"spaceIds": [],
"lightIds": [
2408
],
"spaceGroupIds": []
}
}
]
}
'#
$Json | ConvertFrom-Json |ConvertTo-Expression
[pscustomobject]#{
totalCount = 1
list = ,[pscustomobject]#{
type = 'ToggleLightingState'
order = 1
delay = $Null
postDelay = $Null
name = 'Toggle lighting state of light L-17E-611-KB-1'
parameters = [pscustomobject]#{
relayIds = #()
curveType = $Null
behavior = $Null
duration = $Null
useAssignedSpace = $False
spaceIds = #()
lightIds = ,2408
spaceGroupIds = #()
}
}
}
Or as hashtable:
$Json |ConvertFrom-Json -AsHashTable |ConvertTo-Expression
#{
totalCount = 1
list = ,#{
postDelay = $Null
parameters = #{
duration = $Null
spaceGroupIds = #()
relayIds = #()
spaceIds = #()
useAssignedSpace = $False
curveType = $Null
behavior = $Null
lightIds = ,2408
}
type = 'ToggleLightingState'
delay = $Null
order = 1
name = 'Toggle lighting state of light L-17E-611-KB-1'
}
}

Related

Powershell - Sending an array to JSON

I have been having a problem while automating a task using API. The final JSON output of the Powershell script should look like this:
{
"scopes": [
{
"description": "someDescription",
"scopePath": "somePath"
}
],
"sources": [
{
"eventSource": "SecureScores"
},
{
"eventSource": "SecureScoreControls"
},
{
"eventSource": "SecureScoreControlsSnapshot"
},
{
"eventSource": "SecureScoresSnapshot"
}
],
"actions": [
{
"workspaceResourceId": "someWorkspace",
"actionType": "Workspace"
}
]
}
}
While using [] brackets after "actions" and "sources". However no matter what I try I always end up with something like this
"location": "Test",
"etag": "etag",
"properties": {
"Description": "some description",
"IsEnabled": "true",
"scopes": {
"scopePath": "scopePath",
"description": "scopeDescription",
"sources": {
"eventSource": "SecureScores",
"eventSource3": "SecureScoresSnapshot",
"eventSource2": "SecureScoreControlsSnapshot",
"eventSource1": "SecureScoreControls"
},
"actions": {
"actionType": "Workspace",
"workspaceResourceId": "someID"
}
}
}
}
With the wrong {} brackets. I need this to invoke a REST API code correctly. Any idea how to pass the variables so the JSON would then define those values in an array? I use something like
$RESTjson = $RESTdata | ConvertTo-Json while in $RESTData is a hashtable. Example:
$RESTdata = #{
location = $Tags.Region
etag = "etag"
properties = #{
Description = "some description"
IsEnabled = "true"
scopes = #{
description = "scopeDescription"
scopePath = "scopePath"
}
sources = #{
eventSource = "SecureScores"
eventSource1 = "SecureScoreControls"
eventSource2 = "SecureScoreControlsSnapshot"
eventSource3 = "SecureScoresSnapshot"
}
actions = #{
workspaceResourceId = "someID"
actionType = "Workspace"
}
}
}
Tried messing with -Depth parameter of ConverTo-Json command but without any luck. Various definitons of input values but haven´t found the proper way yet.
Use #(...), the array-subexpression operator, around property values that must become arrays.
If you want to retain the definition order, use [ordered] hashtables (not strictly needed).
Use nested hashtables for those properties that must become their own JSON objects, such as #{ eventSource = "SecureScores" } to become { "eventSource": "SecureScores" } in JSON.
$RESTdata = [ordered] #{
location = $Tags.Region
etag = "etag"
properties = [ordered] #{
Description = "some description"
IsEnabled = "true"
scopes = #(
[ordered] #{
description = "scopeDescription"
scopePath = "scopePath"
}
)
sources = #(
#{ eventSource = "SecureScores" }
#{ eventSource = "SecureScoreControls" }
#{ eventSource = "SecureScoreControlsSnapshot" }
#{ eventSource = "SecureScoresSnapshot" }
)
actions = #(
[ordered] #{
workspaceResourceId = "someID"
actionType = "Workspace"
}
)
}
}
# This yields the desired output as shown in your question.
$RESTData | ConvertTo-Json -Depth 3
Note the unfortunate need to pass a -Depth argument to ConvertTo-Json to avoid data truncation - see this post.
Wrap the lone hashtables in the #(...) array subexpression operator to force PowerShell to wrap and store it in an array:
$RESTdata = #{
location = $Tags.Region
etag = "etag"
properties = #{
Description = "some description"
IsEnabled = "true"
scopes = #{
description = "scopeDescription"
scopePath = "scopePath"
}
sources = #(#{
eventSource = "SecureScores"
eventSource1 = "SecureScoreControls"
eventSource2 = "SecureScoreControlsSnapshot"
eventSource3 = "SecureScoresSnapshot"
})
actions = #(#{
workspaceResourceId = "someID"
actionType = "Workspace"
})
}
}

How to force JSON to be fully displayed for nested arrays [duplicate]

This question already has answers here:
Unexpected ConvertTo-Json results? Answer: it has a default -Depth of 2
(2 answers)
Closed 2 years ago.
I have the following Function that creates a JSON:
Function New-JSONTest {
Param (
[Parameter( ParameterSetName = "NewConfig" )]
[switch]$NewConfig
)
$PSCustomObject = switch ($PSCmdLet.ParameterSetName) {
NewConfig {
[PSCustomObject]#{
Menus = #(
[PSCustomObject]#{
Name = "Produktauswahl"
IsEnabledByDefault = $true
IsVisibleByDefault = $true
IsEnabledIf = ""
IsVisibleIf = ""
OnClickAction = [PSCustomObject]#{
ActionCode = 3
Parameter = #(
[PSCustomObject]#{
ParameterName = "TestInput.Menü"
ParameterType = "string"
ParameterValue = "Menus.Name"
}
)
}
},
[PSCustomObject]#{
Name = "Grundkonfiguration"
IsEnabledByDefault = $false
IsVisibleByDefault = $true
IsEnabledIf = ""
IsVisibleIf = ""
OnClickAction = [PSCustomObject]#{
ActionCode = 3
Parameter = #(
[PSCustomObject]#{
ParameterName = "TestInput.Menü"
ParameterType = "string"
ParameterValue = "Menus.Name"
}
)
}
},
[PSCustomObject]#{
Name = "Zubehörkonfiguration"
IsEnabledByDefault = $false
IsVisibleByDefault = $true
IsEnabledIf = ""
IsVisibleIf = ""
OnClickAction = [PSCustomObject]#{
ActionCode = 3
Parameter = #(
[PSCustomObject]#{
ParameterName = "TestInput.Menü"
ParameterType = "string"
ParameterValue = "Menus.Name"
}
)
}
},
[PSCustomObject]#{
Name = "Konfiguration abschliessen"
IsEnabledByDefault = $false
IsVisibleByDefault = $true
IsEnabledIf = ""
IsVisibleIf = ""
OnClickAction = [PSCustomObject]#{
ActionCode = 3
Parameter = #(
[PSCustomObject]#{
ParameterName = "TestInput.Menü"
ParameterType = "string"
ParameterValue = "Menus.Name"
}
)
}
}
)
}
}
}
# Return as JSON
$PSCustomObject | ConvertTo-Json
}
As you can see, in each Menus Object, I have a OnClickAction Object with another nested PSCustomObject in an array.
When I run the code, each Menu I get returned looks like this:
{
"Name": "Produktauswahl",
"IsEnabledByDefault": true,
"IsVisibleByDefault": true,
"IsEnabledIf": "",
"IsVisibleIf": "",
"OnClickAction": "#{ActionCode=3; Parameter=System.Object[]}"
}
Can I somehow force it to Display my OnClickAction also in an expanded JSON, instead of an array that is not readable? Basically what I need in the End is this:
{
"Menus": [
{
"Name": "Produktauswahl",
"IsEnabledByDefault": true,
"IsVisibleByDefault": true,
"IsEnabledIf": "",
"IsVisibleIf": "",
"OnClickAction": {
"ActionCode": "3",
"Parameter": [
"ParameterName": "TestInput.Menü"
"ParameterType": "string"
"ParameterValue": "Menus.Name"
]
}
}
]
}
Is this possible or am I misunderstanding something?
The default depth of ConvertTo-Json is limited to 2 in the default, but you can set the depth with -Depth. A depth of 5 should be ok for your Json:
$PSCustomObject | ConvertTo-Json -Depth 5

Powershell script to get data from json file

I need to pull data with a particular heading from a json file and output it to a csv file
$data = (Get-Content "C:\Users\QVL6\Downloads\express-ordering-web-
variables.json" | ConvertFrom-Json)
get data
[PSCustomObject[]]$data = #(
[PSCustomObject]#{
Name = 'Name'
Type = 'Type'
Value = 'Value'
Description = 'Description'
}
)
$path = C:\Users\QVL6\
$data | Select-Object -Property Name, Type, Value, Description | Export -Csv
-Path .\data.csv -NoClobber -NoTypeInformation
Json file:
{
"Id": "variableset-Projects-174",
"OwnerId": "Projects-174",
"Version": 23,
"Variables": [
{
"Id": "dfd06d9f-5ab5-0b40-bfed-d11cd0d90e62",
"Name": "apiConfig:orderCommandUrl",
"Value": "http://dev.order-service.local",
"Description": null,
"Scope": {
"Environment": [
"Environments-63"
]
},
"IsEditable": true,
"Prompt": null,
"Type": "String",
"IsSensitive": false
},
{
"Id": "252a19a0-4650-4920-7e66-39a80c1c49ec",
"Name": "apiConfig:orderCommandUrl",
"Value": "http://qa.order-service.local",
"Description": null,
"Scope": {
"Environment": [
"Environments-63",
"Environments-64"
]
},
"IsEditable": true,
"Prompt": null,
"Type": "String",
"IsSensitive": false
},
I want to pull out all the values in Name field
Get-Content already returns a string so you could convert the output directly to json.
$data = Get-Content "C:\Users\myFile\Downloads\express-ordering-web-variables.json" | ConvertFrom-Json
The variable $data is already an object so you don't have to convert it again to a csv. You can directly select the needed headers and export them to a csv.
$data = Get-Content "C:\Users\myFile\Downloads\express-ordering-web-
variables.json" | ConvertFrom-Json
#get some random data
[PSCustomObject[]]$data = #(
[PSCustomObject]#{
H1 = 'Test'
H2 = 'Test2'
},
[PSCustomObject]#{
H1 = 'Test'
H2 = 'Test2'
}
)
$data | Select-Object -Property H1, H2 | Export-Csv -Path $Path -NoClobber -NoTypeInformation

updating values in JSON using PUT method

I have a nested JSON file. I want to update some values with PUT method. I can change some values, but the problem is in the nested values.
$Authorization = "Bearer API-KEY"
$update = [ordered]#{
name = 'ppp'
asset_tag = 'BBB'
custom_fields = #(
[ordered] #{
Mediensatz = #(
[ordered] #{
value = "B2T-XXX"
}
)
}
)
}
$json = $update | ConvertTo-Json -Depth 100
#Write-Host $json
$response = Invoke-RestMethod 'URL' -Method Put -Body $json -ContentType 'application/json' -Headers #{'Authorization' = $Authorization}
My JSON file look like this:
{
"total": 888,
"rows": [
{
"id": 11,
"name": "AAA",
"asset_tag": "CCC",
"model": {
"id": 34,
"name": "TTT"
},
"user_can_checkout": true,
"custom_fields": {
"Mediensatz": {
"field": "lll",
"value": "B2T-YYY",
"field_format": "ANY"
},
"Ueberschreibschutz": {
"field": "lll",
"value": "2019-07-10",
"field_format": "DATE"
}
}
}
I can change the "name" and "asset_tag", but the problem is "value" in custom_fields → Mediensatz → value.
When I try to run my code with Write-Host $json it's look like this:
{
"name": "PPP",
"asset_tag": "BBB",
"custom_fields": [
{
"Mediensatz": [
{
"value": "B2T-XXX"
}
]
}
]
}

PowerShell retrieve MS Graph 3rd level data return non-json result

I got a PS script to retrieve an AuditLog event from MS Graph. The script code is below. It gets the event details in JSON format.
# Create Authentication Token for MS Graph
Function GetAuthToken
{
param
(
[Parameter(Mandatory=$true)]
$TenantName
)
Import-Module Azure
$clientId = "ef9bcdf0-a675-4cd5-9ec3-fa549f9ee4cf"
$redirectUri = "https://RedirectURI.com"
$resourceAppIdURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/$TenantName"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$Credential = Import-Clixml -Path "C:\MIMA\tom_admin_cred.xml"
$AADCredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential" -ArgumentList $credential.UserName,$credential.Password
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId,$AADCredential)
return $authResult
}
Function Get-aAuditEvent
{
param
(
[Parameter(Mandatory=$true)]
$Tenant
)
if($Version -eq $null) {$Version='Beta'}
#------Get the authorization token------#
$token = GetAuthToken -TenantName $tenant
#------Building Rest Api header with authorization token------#
$authHeader = #{
'Content-Type'='application\json'
'Authorization'=$token.CreateAuthorizationHeader()
}
$uri = "https://graph.microsoft.com/beta/auditlogs/directoryAudits/Directory_3WOOD_3967500"
# $uri = "https://graph.microsoft.com/beta/auditlogs/directoryAudits"
Try {
$results = Invoke-RestMethod -Uri $uri –Headers $authHeader –Method Get
$results |ConvertTo-Json -depth 4
}
catch{
Write-Host "Error while retrieving report!" -ForegroundColor red
$auditReports = $_.Exception.Response
}
}
Get-aAuditEvent -Tenant "contoso.onmicrosoft.com"
The result of the code is as below. Notice the content of "modifiedProperties" is not in JSON format? It seems somehow the value of this property has converted to hashtable. However, I tried to put this value into a hashtable and it couldn't parse it properly anyway. Maybe because "newValue" is too long for a hash table?
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#auditLogs/directoryAudits/$entity",
"id": "Directory_3WOOD_3967500",
"category": "Core Directory",
"correlationId": "559450b1-d1e8-4020-a420-4c3c6234ba44",
"result": "success",
"resultReason": "",
"activityDisplayName": "Update user",
"activityDateTime": "2018-10-13T14:57:33.328183Z",
"loggedByService": null,
"initiatedBy": {
"app": null,
"user": {
"id": "9327abf7-93ea-4007-a15c-9b77b5360cc9",
"displayName": null,
"userPrincipalName": "tom-admin#contoso.onmicrosoft.com",
"ipAddress": "\u003cnull\u003e"
}
},
"targetResources": [
{
"#odata.type": "#microsoft.graph.targetResourceUser",
"id": "2a58e6ca-2207-4fc0-ba5d-210cd5de25dc",
"displayName": null,
"userPrincipalName": "tom.chen#contoso.com",
"modifiedProperties": [
"#{displayName=AssignedLicense; oldValue=[]; newValue=[\"[SkuName=ENTERPRISEPACK, AccountId=cdc4b90d-7fa9-4a12-8d58-c2872266673c, SkuId=6fd2c87f-b296-42f0-b197-1e91e994b900, DisabledPlans=[]]\"]}",
"#{displayName=AssignedPlan; oldValue=[]; newValue=[{\"SubscribedPlanId\":\"f0e58183-18c1-4fa6-939b-e78d050533b6\",\"ServiceInstance\":\"To-Do/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:
57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"c87f142c-d1e9-4363-8630-aaea9c4d9ae5\"},{\"SubscribedPlanId\":\"ea0d7e34-84a0-4329-910a-f38d7d4f2c00\",\"ServiceInstance\":\"OfficeForms/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"
2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"2789c901-c14e-48ab-a76a-be334d9d793a\"},{\"SubscribedPlanId\":\"0defa810-1846-4ebf-8c01-4b72f9dbec2c\",\"ServiceInstance\":\"MicrosoftStream/NA001\",\"CapabilityStatus\":0,\"Assi
gnedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"9e700747-8b1d-45e5-ab8d-ef187ceec156\"},{\"SubscribedPlanId\":\"e56c4814-73b8-4a12-ac13-bd2236e1c61c\",\"ServiceInstance\":\"Deskless/NA001\",\"CapabilityStatus
\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"8c7d2df8-86f0-4902-b2ed-a0458298f3b3\"},{\"SubscribedPlanId\":\"ef68b42e-5730-41b8-b119-a78dd199cd39\",\"ServiceInstance\":\"ProcessSimple/NA001\",\"
CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"76846ad7-7776-4c40-a281-a386362dd1b9\"},{\"SubscribedPlanId\":\"d69c693a-dfc8-49f8-9bd2-68b570bc3dd8\",\"ServiceInstance\":\"PowerApp
sService/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"c68f8d98-5534-41c8-bf36-22fa496fa792\"},{\"SubscribedPlanId\":\"b3e7a5a5-bfae-4ae6-887c-ce9665de0610\",\"ServiceIn
stance\":\"TeamspaceAPI/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"57ff2da0-773e-42df-b2af-ffb7a2317929\"},{\"SubscribedPlanId\":\"c9dbc746-7d1d-449f-9a2c-f80c99df11f
2\",\"ServiceInstance\":\"ProjectWorkManagement/PROD_OC_Org_Ring_010\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"b737dad2-2f6c-4c65-90e3-ca563267e8b9\"},{\"SubscribedPlanId\
":\"6aa67dd9-afd1-47c4-b81f-065ba3495692\",\"ServiceInstance\":\"Sway/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"a23b959c-7ce8-4e57-9140-b90eb88a9e97\"},{\"Subscribed
PlanId\":\"6d4d99fc-d0e1-4350-a4da-cb79cadd739e\",\"ServiceInstance\":\"YammerEnterprise/NA009\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"7547a3fe-08ee-4ccb-b430-5077c50416
53\"},{\"SubscribedPlanId\":\"ac1fca1c-7d64-476c-b1f8-1c336ccac213\",\"ServiceInstance\":\"RMSOnline/AP\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"bea4c11e-220a-4e6d-8eb8-8
ea15d019f90\"},{\"SubscribedPlanId\":\"2cc87a99-6c05-4bf2-a8a7-4a75e26a6afd\",\"ServiceInstance\":\"MicrosoftOffice/NorthAmerica\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"
43de0ff5-c92c-492b-9116-175376d08c38\"},{\"SubscribedPlanId\":\"97006162-e810-4814-98e7-3ae3745b28bc\",\"ServiceInstance\":\"MicrosoftCommunicationsOnline/Instance04-S\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\
"Capability\":null,\"ServicePlanId\":\"0feaeb32-d00e-4d66-bd5a-43b5b83db82c\"},{\"SubscribedPlanId\":\"10985cf4-2206-4e47-9910-426586912b1a\",\"ServiceInstance\":\"SharePoint/SPOS0017\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"Initi
alState\":null,\"Capability\":null,\"ServicePlanId\":\"e95bec33-7c88-4a70-8e19-b10bd9d0c014\"},{\"SubscribedPlanId\":\"e0592405-cc57-4152-8cc0-3f8e5651e47d\",\"ServiceInstance\":\"SharePoint/SPOS0017\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.16
83839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"5dbe027f-2339-4123-9542-606e4d348a72\"},{\"SubscribedPlanId\":\"552916d8-55f1-44be-a7e1-9a56b8086a9b\",\"ServiceInstance\":\"exchange/apcprd03-001-01\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2
018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"efb87545-963c-4e0d-99df-69c6916d9eb0\"}]}",
"#{displayName=Included Updated Properties; oldValue=; newValue=\"AssignedLicense, AssignedPlan\"}",
"#{displayName=TargetId.UserType; oldValue=; newValue=\"Member\"}"
]
}
],
"additionalDetails": [
{
"key": "UserType",
"value": "Member"
}
]
}
This is very odd, as when I retrieve the same event from MS Graph Explorer, I get different result, which is all in proper JSON foramt. Below is the output from MS Graph Explorer. As you can see, the "modifiedProperties" pair is still presented in JSON format.
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#auditLogs/directoryAudits/$entity",
"id": "Directory_3WOOD_3967500",
"category": "Core Directory",
"correlationId": "559450b1-d1e8-4020-a420-4c3c6234ba44",
"result": "success",
"resultReason": "",
"activityDisplayName": "Update user",
"activityDateTime": "2018-10-13T14:57:33.328183Z",
"loggedByService": null,
"initiatedBy": {
"app": null,
"user": {
"id": "9327abf7-93ea-4007-a15c-9b77b5360cc9",
"displayName": null,
"userPrincipalName": "tom-admin#contoso.onmicrosoft.com",
"ipAddress": "<null>"
}
},
"targetResources": [
{
"#odata.type": "#microsoft.graph.targetResourceUser",
"id": "2a58e6ca-2207-4fc0-ba5d-210cd5de25dc",
"displayName": null,
"userPrincipalName": "tom.chen#contoso.com",
"modifiedProperties": [
{
"displayName": "AssignedLicense",
"oldValue": "[]",
"newValue": "[\"[SkuName=ENTERPRISEPACK, AccountId=cdc4b90d-7fa9-4a12-8d58-c2872266673c, SkuId=6fd2c87f-b296-42f0-b197-1e91e994b900, DisabledPlans=[]]\"]"
},
{
"displayName": "AssignedPlan",
"oldValue": "[]",
"newValue": "[{\"SubscribedPlanId\":\"f0e58183-18c1-4fa6-939b-e78d050533b6\",\"ServiceInstance\":\"To-Do/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"c87f142c-d1e9-4363-8630-aaea9c4d9ae5\"},{\"SubscribedPlanId\":\"ea0d7e34-84a0-4329-910a-f38d7d4f2c00\",\"ServiceInstance\":\"OfficeForms/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"2789c901-c14e-48ab-a76a-be334d9d793a\"},{\"SubscribedPlanId\":\"0defa810-1846-4ebf-8c01-4b72f9dbec2c\",\"ServiceInstance\":\"MicrosoftStream/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"9e700747-8b1d-45e5-ab8d-ef187ceec156\"},{\"SubscribedPlanId\":\"e56c4814-73b8-4a12-ac13-bd2236e1c61c\",\"ServiceInstance\":\"Deskless/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"8c7d2df8-86f0-4902-b2ed-a0458298f3b3\"},{\"SubscribedPlanId\":\"ef68b42e-5730-41b8-b119-a78dd199cd39\",\"ServiceInstance\":\"ProcessSimple/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"76846ad7-7776-4c40-a281-a386362dd1b9\"},{\"SubscribedPlanId\":\"d69c693a-dfc8-49f8-9bd2-68b570bc3dd8\",\"ServiceInstance\":\"PowerAppsService/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"c68f8d98-5534-41c8-bf36-22fa496fa792\"},{\"SubscribedPlanId\":\"b3e7a5a5-bfae-4ae6-887c-ce9665de0610\",\"ServiceInstance\":\"TeamspaceAPI/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"57ff2da0-773e-42df-b2af-ffb7a2317929\"},{\"SubscribedPlanId\":\"c9dbc746-7d1d-449f-9a2c-f80c99df11f2\",\"ServiceInstance\":\"ProjectWorkManagement/PROD_OC_Org_Ring_010\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"b737dad2-2f6c-4c65-90e3-ca563267e8b9\"},{\"SubscribedPlanId\":\"6aa67dd9-afd1-47c4-b81f-065ba3495692\",\"ServiceInstance\":\"Sway/NA001\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"a23b959c-7ce8-4e57-9140-b90eb88a9e97\"},{\"SubscribedPlanId\":\"6d4d99fc-d0e1-4350-a4da-cb79cadd739e\",\"ServiceInstance\":\"YammerEnterprise/NA009\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"7547a3fe-08ee-4ccb-b430-5077c5041653\"},{\"SubscribedPlanId\":\"ac1fca1c-7d64-476c-b1f8-1c336ccac213\",\"ServiceInstance\":\"RMSOnline/AP\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"bea4c11e-220a-4e6d-8eb8-8ea15d019f90\"},{\"SubscribedPlanId\":\"2cc87a99-6c05-4bf2-a8a7-4a75e26a6afd\",\"ServiceInstance\":\"MicrosoftOffice/NorthAmerica\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"43de0ff5-c92c-492b-9116-175376d08c38\"},{\"SubscribedPlanId\":\"97006162-e810-4814-98e7-3ae3745b28bc\",\"ServiceInstance\":\"MicrosoftCommunicationsOnline/Instance04-S\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"0feaeb32-d00e-4d66-bd5a-43b5b83db82c\"},{\"SubscribedPlanId\":\"10985cf4-2206-4e47-9910-426586912b1a\",\"ServiceInstance\":\"SharePoint/SPOS0017\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"e95bec33-7c88-4a70-8e19-b10bd9d0c014\"},{\"SubscribedPlanId\":\"e0592405-cc57-4152-8cc0-3f8e5651e47d\",\"ServiceInstance\":\"SharePoint/SPOS0017\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"5dbe027f-2339-4123-9542-606e4d348a72\"},{\"SubscribedPlanId\":\"552916d8-55f1-44be-a7e1-9a56b8086a9b\",\"ServiceInstance\":\"exchange/apcprd03-001-01\",\"CapabilityStatus\":0,\"AssignedTimestamp\":\"2018-10-13T14:57:33.1683839Z\",\"InitialState\":null,\"Capability\":null,\"ServicePlanId\":\"efb87545-963c-4e0d-99df-69c6916d9eb0\"}]"
},
{
"displayName": "Included Updated Properties",
"oldValue": null,
"newValue": "\"AssignedLicense, AssignedPlan\""
},
{
"displayName": "TargetId.UserType",
"oldValue": null,
"newValue": "\"Member\""
}
]
}
],
"additionalDetails": [
{
"key": "UserType",
"value": "Member"
}
]
}
In fact both results (via PowerShell and Microsoft Graph Explorer) seems to be identical (except some formatting differences).
In both cases a valid JSON value is returned.
Now comes the turn of oldValue and newValue property values.
According to documentation, modifiedProperty property of targetResource resource
returns the collection of name, old value and new value which represented in JSON format like this:
{
"displayName": "String",
"newValue": "String",
"oldValue": "String"
}
meaning newValue and oldValue return the converted to string values.
Example
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#auditLogs/directoryAudits/$entity",
"id": "Directory_GIRJA_107870298",
//...
"targetResources": [
{
"#odata.type": "#microsoft.graph.targetResourceGroup",
//...
"modifiedProperties": [
{
"displayName": "foo",
"oldValue": "[]",
"newValue": "[\"bar\"]"
},
//...
{
"displayName": "json_value",
"oldValue": null,
"newValue": "[{\"first_name\":\"Jon\",\"last_name\":\"Doe\"}]"
}
]
}
],
"additionalDetails": []
}
Note: pay attention to the second modifiedProperty entry newValue property, which represents JSON value and is returned as a string: {"first_name":"Jon","last_name":"Doe"}
Using the following example newValue could be converted to JSON:
$uri = "https://graph.microsoft.com/beta/auditLogs/directoryAudits/{directory-id}"
$results = Invoke-RestMethod -Uri $uri -Headers $headers -Method Get
$results.targetResources | Select -ExpandProperty modifiedProperties | Select -ExpandProperty newValue | ConvertFrom-Json
I managed to solve the problem by putting the "modifiedProperties" section into a hashtable (Didn't do this properly last time). I use a function to convert the JSON result to Hashtable. The function code is copied from here.
Function ConvertTo-Hashtable {
[CmdletBinding()]
[OutputType('hashtable')]
param (
[Parameter(ValueFromPipeline)]
$InputObject
)
process {
## Return null if the input is null. This can happen when calling the function
## recursively and a property is null
if ($null -eq $InputObject) {
return $null
}
## Check if the input is an array or collection. If so, we also need to convert
## those types into hash tables as well. This function will convert all child
## objects into hash tables (if applicable)
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
$collection = #(
foreach ($object in $InputObject) {
ConvertTo-Hashtable -InputObject $object
}
)
## Return the array but don't enumerate it because the object may be pretty complex
Write-Output -NoEnumerate $collection
} elseif ($InputObject -is [psobject]) { ## If the object has properties that need enumeration
## Convert it to its own hash table and return it
$hash = #{}
foreach ($property in $InputObject.PSObject.Properties) {
$hash[$property.Name] = ConvertTo-Hashtable -InputObject $property.Value
}
$hash
} else {
## If the object isn't an array, collection, or other object, it's already a hash table
## So just return it.
$InputObject
}
}
}
$hashtable1 = #{}
$hashtable2 = #{}
$hashtable1 = Get-aAuditEvent -Tenant "contoso.onmicrosoft.com"|ConvertFrom-Json|ConvertTo-HashTable
$hashtable2 = $hashtable1.targetResources.modifiedProperties
$hashtable2[0].displayName
$hashtable2[0].oldValue
$hashtable2[0].newValue
The output of the code is below. I still need to workout how to parse "newValue" properly. But at least I can show what actions have been done and what have been changed.
AssignedLicense
[]
["[SkuName=ENTERPRISEPACK, AccountId=cdc4b90d-7fa9-4a12-8d58-c2872266673c, SkuId=6fd2c87f-b296-42f0-b197-1e91e994b900, DisabledPlans=[]]"]