List inside JSON Powershell - json

I am trying to parse the following JSON into a PSCustomObject
[
{
"tags": [
{
"tagName": "Microsoft Teams"
},
{
"tagName": "Worldwide (Standard Multi-Tenant)"
},
{
"tagName": "General Availability"
},
{
"tagName": "Web"
},
{
"tagName": "Desktop"
}
],
"tagsContainer": {
"products": [
{
"tagName": "Microsoft Teams"
}
],
"cloudInstances": [
{
"tagName": "Worldwide (Standard Multi-Tenant)"
}
],
"releasePhase": [
{
"tagName": "General Availability"
}
],
"platforms": [
{
"tagName": "Web"
},
{
"tagName": "Desktop"
}
]
},
"id": 51230,
"title": "Microsoft Teams: New file sharing experience",
"description": "Streamline sharing with Microsoft Teams. You can now create a shareable link for any file stored in Teams and directly set the appropriate permissions. Additionally, you can also set permissions for files stored in SharePoint or OneDrive while composing a private chat or starting a channel conversation.",
"status": "Launched",
"moreInfoLink": "https://techcommunity.microsoft.com/t5/microsoft-sharepoint-blog/rich-new-file-and-sharing-experiences-throughout-microsoft-365/ba-p/960129",
"publicRoadmapStatus": "Include this month",
"created": "2019-05-08T07:00:00",
"modified": "2022-01-13T00:05:19.663",
"publicDisclosureAvailabilityDate": "March CY2021",
"publicPreviewDate": ""
}
]
I have that JSON stored in a variable like this:
$RoadmapContent = Get-Content -Raw -Path ".\M365Roadmap_single.json" | ConvertFrom-Json
And this would be my PSCustomObject:
$RoadmapItems =[PSCustomObject]#{
Title = $($RoadmapContent.title)
Tags = $($RoadmapContent.tags)
}
I would like to have this tags in a single column, like this: Microsoft Teams, Worldwide (Standard Multi-Tenant), General Availability, Web, Desktop
I have tried to accomplish that (unsuccessfully) like this:
$RoadmapContent.Tags -join ";"
How can I parse this?
Many thanks!
Edit:
I can access the tags like this:
foreach ($tag in $RoadmapContent.tags) {Write-Host $Tag.tagName}
But cannot figure out how to use this in a PSCustomObject

Figured it out thanks to a comment in the original question, here's the full code:
$RoadmapContent = Get-Content -Raw -Path ".\M365Roadmap_single.json" | ConvertFrom-Json
$RoadmapItems =[PSCustomObject]#{
Title = $($RoadmapContent.title)
Tags = $($RoadmapContent.tags.tagname -join ', ')
}
$RoadmapItems

Related

Export fields with multiple nested values from JSON to CSV

I need to import some JSON data am getting into my database. I'd like to use PowerShell and figured out a little, but I need help getting the final piece together.
Here is my existing PowerShell script.
Get-Content -Path "t:\1.json" |
ConvertFrom-Json |
Select-Object -expand data |
ConvertTo-Csv -NoTypeInformation |
Set-Content "t:\1.csv"
It does everything but doesnot get the badges details out in single cav along with user name. My question is, how can I get all details in single csv?
Here is my JSON data:
{
"data": [
{
"name": "Shiva",
"email": "Shiva#example.com",
"organization": "Team",
"badges": {
"data": [
{
"name": "AWS Certified Developer",
"id": "001"
}
]
},
"id": "1001"
},
{
"name": "Rudra",
"email": "Rudra#example.com",
"organization": "Team",
"badges": {
"data": [
{
"name": "Certified Google Associate Cloud Engineer",
"id": "006"
}
]
},
"id": "1002"
},
{
"name": "Alazar",
"email": "Alazar#example.com",
"organization": "Team",
"badges": {
"data": [
{
"name": "Google Cloud Data Engineer Certified",
"id": "007"
},
{
"name": "Google Certified Professional Cloud Network Engineer",
"id": "008"
},
{
"name": "AWS Solution Architect",
"id": "009"
},
{
"name": "Certified Google Associate Cloud Engineer",
"id": "006"
}
]
},
"id": "1003"
}
]
}
You need to add new rows of data for each badge a person can have.
Something like this:
(Get-Content -Path 't:\1.json' -Raw | ConvertFrom-Json).data | ForEach-Object {
foreach ($badge in $_.badges.data) {
$_ | Select-Object *,
#{Name = 'badge_id'; Expression = { $badge.id }},
#{Name = 'badge_name'; Expression = { $badge.name }} -ExcludeProperty badges
}
} | Export-Csv -Path 't:\1.csv' -NoTypeInformation
After this, file 't:\1.csv' will look like this:
"name","email","organization","id","badge_id","badge_name"
"Shiva","Shiva#example.com","Team","1001","001","AWS Certified Developer"
"Rudra","Rudra#example.com","Team","1002","006","Certified Google Associate Cloud Engineer"
"Alazar","Alazar#example.com","Team","1003","007","Google Cloud Data Engineer Certified"
"Alazar","Alazar#example.com","Team","1003","008","Google Certified Professional Cloud Network Engineer"
"Alazar","Alazar#example.com","Team","1003","009","AWS Solution Architect"
"Alazar","Alazar#example.com","Team","1003","006","Certified Google Associate Cloud Engineer"

How to select words after /slash from a json file in a powershell script

I've a json file from a az cli command, I want to deploy with a powershell script from a tool like jenkins or rundeck, I need to take the field "name" from json but not entirely only the word after forward slash
[
{
"Group": "KC-EMEA-RSGP-BPTRAINING-01",
"id": "/subscriptions/KC-EMEA-RSGP-BPTRAINING-01/providers/Microsoft.Sql/servers/",
"name": "kc-emea-sqsrv-bptraining-dev-01/master"
},
{
"Group": "KC-EMEA-RSGP-NAVISIONKM-DEV-01",
"id": "/subscriptions/KC-EMEA-RSGP-NAVISIONKM-DEV-01/providers/Microsoft.Sql/servers/",
"name": "km-emea-sqsrv-navision-tst-01/km-emea-sqdb-navision-tst-01"
},
{
"Group": "KC-EMEA-RSGP-NAVISIONKM-DEV-01",
"id": "/subscriptions/KC-EMEA-RSGP-NAVISIONKM-DEV-01/providers/Microsoft.Sql/servers/",
"name": "km-emea-sqsrv-navision-tst-01/master"
},
{
"Group": "KC-EMEA-RSGP-PROJECTS-DEV-01",
"id": "/subscriptions/KC-EMEA-RSGP-PROJECTS-DEV-01/providers/Microsoft.Sql/servers/",
"name": "kc-emea-sqsrv-projects-dev-01/KC-EMEA-SQDB-BPTRAINING-TRAINEE-01"
}
]
$file = "pathtojsonfile.json"
$jsonContent = Get-Content $file | ConvertFrom-Json;
$namedb = $jsonContent.name;
$value= $namedb.Substring($namedb.IndexOf('/')+1) --> this doesn't work.
Try
$namedb[0].Substring($namedb[0].IndexOf('/')+1)
And for all of them:
foreach($name in $namedb) {$name.Substring($name.IndexOf('/')+1)}

ConvertFrom-JSON won't accept convertto-json with children when working with WebServiceProxy

I am pulling data from an API using the New-WebServiceProxy in PowerShell 4.0 and then piping it out to a JSON file for review and import on another API service (same API version, etc, just a different host).
$tasklist.Taskconfig | ConvertTo-JSON-Depth 50 -As String | Out-File -FilePath $exportpath\$name.xml -Force
Gives me my XML containing the TaskConfig. In this case, TaskConfig is an object type automatically generated by the API I'm interfacing with. When I want to import the content I am using:
$taskconfig = (Get-Content "$taskjson") -join "`n" | ConvertFrom-Json
but when I run this it's unable to create the object. I assume this is because the JSON contains nested children, giving the error-
Cannot convert value "#{Name=plugindive; Value=;> Children=System.Object[]}" to type "Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1rcleWeb_WebClientAPI_asmx_wsdl.TaskConfig". Error: "Cannot convert the "#{Name=plugindive; Value=;Children=System.Object[]}" value of type "System.Management.Automation.PSCustomObject" to type "Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1rcleWeb_WebClientAPI_asmx_wsdl.TaskConfig"."
I've tried explictly stating the type of object:
$taskconfig = [Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1rcleWeb_WebClientAPI_asmx_wsdl.TaskConfig](Get-Content "$taskjson" | Out-string | ConvertFrom-Json)
as well as creating the object then trying to add the children from my JSON -
$taskconfig.children = $json.children
But these all fail in the same way.
I don't seem to get this same issue in PowerShell 5.0 interestingly enough, but I can't verify why - is there another way to approach this?
Added example JSON below
{"Name": "plugindive",
"Value": null,
"Children": [{
"Name": "auto",
"Value": "False",
"Children": [
]
},
{
"Name": "categories",
"Value": null,
"Children": [{
"Name": "Module Z",
"Value": "False",
"Children": [
]
},
{
"Name": "Module A",
"Value": "False",
"Children": [
]
},
{
"Name": "Module B",
"Value": "False",
"Children": [
]
},
{
"Name": "Module C",
"Value": "False",
"Children": [
]
}
]
}
]
}
It seems as if this doesn't work in PowerShell v3.0, so I simply ended up making posts with the explicit XML directly, rather than converting to JSON.

Editing a .json file using powershell

I have a .json file that needs to be edited in User Data, so I will have to use powershell to accomplish this.
The json looks something like this:
{
"EngineConfiguration": {
"PollInterval": "00:00:15",
"Components": [
{
"Id": "CustomLogs",
"FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"LogDirectoryPath": "C:\\CustomLogs\\",
"TimestampFormat": "MM/dd/yyyy HH:mm:ss",
"Encoding": "UTF-8",
"Filter": "",
"CultureName": "en-US",
"TimeZoneKind": "Local"
}
}
],
"Flows": {
"Flows":
[
"(ApplicationEventLog,SystemEventLog),CloudWatchLogs"
]
}
}
}
I would like it to look like this --
{
"EngineConfiguration": {
"PollInterval": "00:00:15",
"Components": [
{
"Id": "CustomLogs",
"FullName": "AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch",
"Parameters": {
"LogDirectoryPath": "C:\\ProgramData\\Amazon\\CodeDeploy\\deployment-logs",
"TimestampFormat": "[yyyy-MM-dd HH:mm:ss.fff]",
"Encoding": "UTF-8",
"Filter": "",
"CultureName": "en-US",
"TimeZoneKind": "Local"
}
}
],
"Flows": {
"Flows":
[
"(ApplicationEventLog,SystemEventLog, CustomLogs),CloudWatchLogs"
]
}
}
}
In the Custom Logs Parameters, the LogDirectoryPath and TimestampFormat have both changed. Also, in the Flows section, I have added the 'CustomLogs' to the CloudWatch Group.
I tried making it work with code like this:
$a = Get-Content 'C:\PATH\TO\file.json' -raw | ConvertFrom-Json
$a.EngineConfiguration.Components[0].Parameters = '{"LogDirectoryPath": "","TimestampFormat": "[yyyy-MM-dd HH:mm:ss.fff]","Encoding": "UTF-8","Filter": "","CultureName": "en-US","TimeZoneKind": "Local"}'
$a | ConvertTo-Json | set-content 'C:\PATH\TO\output.json'
But that produces a very ugly output
{
"EngineConfiguration": {
"PollInterval": "00:00:15",
"Components": [
"#{Id=CustomLogs; FullName=AWS.EC2.Windows.CloudWatch.CustomLog.CustomLogInputComponent,AWS.EC2.Windows.CloudWatch; Parameters={\"LogDirectoryPath\": \"\",\"TimestampFormat\": \"[yyyy-MM-dd HH:mm:ss.fff]\",\"Encoding\": \"UTF-8\",\"Filter\": \"\",\"CultureName\": \"en-US\",\"TimeZoneKind\": \"Local\"}}",
"#{Id=CloudWatchLogs; FullName=AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch; Parameters=}"
],
"Flows": {
"Flows": "(ApplicationEventLog,SystemEventLog),CloudWatchLogs"
}
}
}
Is there a more elegant way to do this? Any advice would be greatly appreciated. Thanks!
Try using the -Depth switch for ConvertTo-Json. By default this compresses any child elements beyond a depth of 2 to the string representations of the object you have seen:
"#{Id=CustomLogs; etc."
By specifying a deeper depth you get a format more like the one you want. Combine this with something that compresses the excessive whitespace as so:
((ConvertFrom-Json $a) | ConvertTo-Json -Depth 4) -replace ((" "*4)," ")
It would be possible to reduce the leading whitespace with a regex. However, that does not really produce the reformatting, pretty-print that you say you want.
$a | ConvertTo-Json | % {$_ -replace " "," "} | set-content 'output.json'

ARM listKeys() Function - How to retrieve OMS/OpsInsight Workspace keys?

As part of a template I want to retrieve the SharedKeys of an OMS / Operational Insights Workspace, rather than having to pass it in as a parameter.
Is this possible? I'm following the documentation here
It does not appear that the Microsoft.OperationalInsights/workspaces/ resource provider has any list* provider operations, and I can't find any reference for other:
Get-AzureRmProviderOperation -OperationSearchString * | where {$_.Operation -like "*operational*sharedkeys*"} | FT Operation
Microsoft.OperationalInsights/workspaces/sharedKeys/action
My desired usage:
"variables": { workspaceKey: "[listKeys(parameters('workspaceResourceId'), '2015-05-01-preview').primarySharedKey]" }
In the meantime, assuming this isn't actually supported, I added a request for it on the Log Analytics UserVoice site
Per Ryan Jones, [listKeys()] against the OMS Workspace will work as expected and return a JSON object with primarySharedKey & secondarySharedKey properties:
"outputs": {
"listKeys": {
"value": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview')]",
"type": "object"
}
}
yields:
{
"primarySharedKey":"",
"secondarySharedKey":""
}
Important Caveat:
listKeys() can not be specified in the variables section of an ARM template, since it derives its value from a runtime state.
See this blog post for how to use a Linked Template, specified as a resource, in order to retrieve the output value and assign it to a property in another resource.
Alternatively, you can use it directly. Here is my final template:
(don't actually keep the keys in the output!)
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspaceResourceId": { "type": "string" },
"virtualMachines": { "type": "array" }
},
"variables": {
"extensionType": {
"Windows": "MicrosoftMonitoringAgent",
"Linux": "OmsAgentForLinux"
}
},
"resources": [
{
"copy": {
"name": "VMMonitoringExtensionsCopy",
"count": "[length(parameters('virtualMachines'))]"
},
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('virtualMachines')[copyIndex()].location]",
"name": "[concat(parameters('virtualMachines')[copyIndex()].name, '/Microsoft.EnterpriseCloud.Monitoring')]",
"properties": {
"publisher": "Microsoft.EnterpriseCloud.Monitoring",
"type": "[variables('extensionType')[parameters('virtualMachines')[copyIndex()].osType]]",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"workspaceId": "[reference(parameters('workspaceResourceId'), '2015-11-01-preview').customerId]"
},
"protectedSettings": {
"workspaceKey": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview').primarySharedKey]"
}
}
}
],
"outputs": {
"workspaceCustomerId": {
"value": "[reference(parameters('workspaceResourceId'), '2015-11-01-preview').customerId]",
"type": "string"
},
"workspacePrimarySharedKey": {
"value": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview').primarySharedKey]",
"type": "securestring"
},
"workspaceSecondarySharedKey": {
"value": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview').secondarySharedKey]",
"type": "securestring"
}
}
}
The array parameter virtualMachines follows this schema:
[
{ "name": "", "location": "", "osType": "" }
]
listKeys requires that you put the resource type in. So have you tried this?
"variables": { workspaceKey: "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspaceResourceId'), '2015-05-01-preview').primarySharedKey]" }
Unfortunately, atm there is nothing at all in the Azure quickstart repo on that resource so I'm not 100% sure...
But passing it in as a parameter would be fine. You could do this... In your deployment script, before you run New-AzureRmResourceGroupDeployment, create/use existing workspace, get key, pass in as param, create primarySharedKey as a param in the template:
$workSpace = Get-AzureRmOperationalInsightsWorkspace -ResourceGroupName $RGName -Name $workSpaceName -ErrorAction SilentlyContinue
if($workSpace -eq $null){
New-AzureRmOperationalInsightsWorkspace -ResourceGroupName $RGName -Name $workSpaceName -Location $Location
}
$keys = Get-AzureRmOperationalInsightsWorkspaceSharedKeys -ResourceGroupName $RGName -Name $workSpaceName
New-AzureRmResourceGroupDeployment <other stuff here> -primarySharedKey $keys.PrimarySharedKey