powershell with JSON and embedded objects - json

I have following ConvertFrom-Json output from JSON file:
Id : 1
ItemName : TestFile
SharingInformation : {#{RecipientEmail=complianceadmin#dev.onmicrosoft.com; ResharePermission=Read}, #{RecipientEmail=test#dev.onmicrosoft.com; ResharePermission=Read}}
I would like to save this data to .csv file in following manner as columns:
Id : 1
ItemName : TestFile
RecipientEmail : test#dev.domain.com; test2#dev.domain.com
ResharePermission : Read; Write
as columns.. Here you can find part of my actual PS code (which do not work properly when there is more than one embedded values):
$JSONFile = $ExctratedFile | ConvertFrom-Json
$psObjectForCsv = $JSONFile | ForEach-Object {
[PSCustomObject]#{
"id"=$_.Id
"ItemName"=$_.ItemName
"RecipientEmail"=$_.SharingInformation.RecipientEmail
"ResharePermission"=$_.SharingInformation.ResharePermission
}
}
$psObjectForCsv | Export-Csv -path $fileName -Force -NoTypeInformation
}
do you have any ideas how to achieve this?
Thank you for your help!
Regards

Join multiple values with a delimiter:
$psObjectForCsv = $data | ForEach-Object {
[PSCustomObject]#{
id = $_.Id
ItemName = $_.ItemName
RecipientEmail = $_.SharingInformation.RecipientEmail -join ";"
ResharePermission = $_.SharingInformation.ResharePermission -join ";"
}
}

Related

marge embedded JSON objects with powershell

I have following ConvertFrom-Json output from JSON file:
Id : 1
ItemName : TestFile
SharingInformation : {#{RecipientEmail=complianceadmin#dev.onmicrosoft.com; ResharePermission=Read}, #{RecipientEmail=test#dev.onmicrosoft.com; ResharePermission=Read}}
I would like to save this data to .csv file in following manner as columns:
Id : 1
ItemName : TestFile
Users : (read) test#dev.domain.com ; (write) test2#dev.domain.com
as columns.. Here you can find part of my actual PS code (which do not work properly when there is more than one embedded values):
$JSONFile = $ExctratedFile | ConvertFrom-Json
$psObjectForCsv = $JSONFile | ForEach-Object {
[PSCustomObject]#{
"id"=$_.Id
"ItemName"=$_.ItemName
"RecipientEmail"=$_.SharingInformation.RecipientEmail
"ResharePermission"=$_.SharingInformation.ResharePermission
}
}
$psObjectForCsv | Export-Csv -path $fileName -Force -NoTypeInformation
}
do you have any ideas how to achieve this?
Thank you for your help!
Regards
You can format the SharingInformation in any form you like.
Try
$JSONFile = $ExctratedFile | ConvertFrom-Json
$result = $JSONFile | ForEach-Object {
# output a formatted string "(permission) emailaddress"
$users = foreach ($shareInfo in $_.SharingInformation) {
'({0}) {1}' -f $shareInfo.ResharePermission, $shareInfo.RecipientEmail
}
[PSCustomObject]#{
id = $_.Id
ItemName = $_.ItemName
Users = $users -join "; "
}
}
$result | Export-Csv -Path $fileName -Force -NoTypeInformation

How to Get the values from json using powershell

Guys this is my JSON file and I want to create a PowerShell script which will give me result like
I have used method like Get-Content and other but there are some issues with the JSON parsing. Please find what is my requirement I have explained in details below.
MyLocalMachineHome
LocalMachine = Sahil_LocalMachine
Second_MyLocalMachine = Sahil_MylocalMachine
Second_MyLocalMachine = ""
Staging
Second_Staging = Sahil;_Secconf
Staging = Sahil_Staging
third_staging = stsajiii
There is also one functionality which I would like to have if I want to get only variables of "staging".
I was using this function Get-Content -Raw -Path E:\shell\Powershell\1ReleasePipelines.json | ConvertFrom-Json | select -ExpandProperty variables on my original JSON file but somehow there is some kind of limit in storing string which I was getting from this method.
{
"environments": [
{
"id": 3,
"name": "MyLocalMachineHome",
"variableGroups": [],
"variables": {
"LocalMachine": {
"value": "Sahil_LocalMachine"
},
"Second_MyLocalMachine": {
"value": "Sahil_MylocalMachine"
},
"thirf_mylocal": {
"value": ""
}
}
},
{
"id": 7,
"name": "Staging",
"variableGroups": [],
"variables": {
"Second_Staging": {
"value": "Sahil;_Secconf"
},
"Staging": {
"value": "Sahil_Staging"
},
"third_staging": {
"value": "stsajiii"
}
}
}
]
}
If we assume that $json contains your JSON content, you can do the following ugly code:
$environment = 'staging'
$j = $json | ConvertFrom-Json
($j.environments | where name -eq $environment).variables | Foreach-Object {
$CurrentObject = $_
$CurrentObject | Get-Member -MemberType NoteProperty |
Select-Object -Expand Name | Foreach-Object {
$CurrentObject.$_.value
}
}
It appears your issue is that you don't know what variables are going to be contained within your JSON. So you can't easily use Select-Object variable or $object.variable. You need a dynamic approach.
If you know your variables ahead of time, things become simpler. You can store your variable names in an array and loop over them.
$variables = 'Second_Staging','Staging','third_staging'
$environment = 'staging'
$j = $json | ConvertFrom-Json
$jsonVars = ($j.environments | where name -eq $environment).variables
$variables | Foreach-Object {
$jsonVars.$_.value
}
View all the sub-properties of variables with format-list instead of format-table. Since the properties vary, format-table won't show all of them. There's a lot of sloppy object construction in json.
$a = get-content file.json
$a.environments.variables | format-table
LocalMachine Second_MyLocalMachine thirf_mylocal
------------ --------------------- -------------
#{value=Sahil_LocalMachine} #{value=Sahil_MylocalMachine} #{value=}
$a.environments.variables | format-list
LocalMachine : #{value=Sahil_LocalMachine}
Second_MyLocalMachine : #{value=Sahil_MylocalMachine}
thirf_mylocal : #{value=}
Second_Staging : #{value=Sahil;_Secconf}
Staging : #{value=Sahil_Staging}
third_staging : #{value=stsajiii}
Get the staging variables?
$a.environments | where name -eq staging | foreach variables
Second_Staging Staging third_staging
-------------- ------- -------------
#{value=Sahil;_Secconf} #{value=Sahil_Staging} #{value=stsajiii}
cls
start-transcript -path 'C:\E\Devops\PowerShell_Chapters\ABC.txt'
write-output "**********Variables of Release************"
get-content -raw -path 'C:\E\Devops\PowerShell_Chapters\Release.json'| Convertfrom-Json | Select -ExpandProperty variables
$json = get-content -raw -path 'C:\E\Devops\PowerShell_Chapters\Release.json'| Convertfrom-Json | Select -ExpandProperty environments
$EnvirnomentsVariables = get-content -raw -path 'C:\E\Devops\PowerShell_Chapters\Release.json'| Convertfrom-Json | Select -ExpandProperty environments |Select -ExpandProperty name
$ReleaseVariable = get-content -raw -path 'C:\E\Devops\PowerShell_Chapters\Release.json'| Convertfrom-Json | Select -ExpandProperty environments |Select -ExpandProperty variables
$i = 0
foreach($a in $EnvirnomentsVariables)
{
$ABC_Staging = $EnvirnomentsVariables[$i]
#write-output $ABC_Staging
if( $ABC_Staging -match "ABC Staging")
{
write-output "****************Variables of " $EnvirnomentsVariables[$i]*************"
#add-content 'C:\E\Devops\PowerShell_Chapters\ABC.txt' $EnvirnomentsVariables[$i]
# Set-content -path 'C:\E\Devops\PowerShell_Chapters\Sahil.json'| ConvertTo-Json | select $EnvirnomentsVariables[$i]
write-output $ReleaseVariable[$i]
# add-content 'C:\E\Devops\PowerShell_Chapters\ABC.txt' $ReleaseVariable[$i]
# Set-content -path 'C:\E\Devops\PowerShell_Chapters\Sahil.json'| ConvertTo-Json | select $ReleaseVariable[$i]
}
$i = $i + 1
}
stop-transcript

how to prevent PowerShell adding \ to a string

I'm currently working with Powershell editing JSONs
My JSON looks like this:
{
"value": ["E_"]
}
I only want to add a specific number after E_.
The result should look like this:
{
"value": ["E_5"]
}
My PS Script:
$tdePath = 'C:\temp\tde.csv'
$dirName = Get-ChildItem -Path $rootDir -Filter TDE_Config.json -Recurse -ErrorAction SilentlyContinue -Force | Select-Object DirectoryName | Export-Csv $tdePath -NoTypeInformation
$importTDEJson = Import-Csv $tdePath -Encoding UTF8 | % {
[String]$nr = $_.DirectoryName.Split('\')[6].split(' ')[4]
$full_path = $_.DirectoryName + "\TDE_Config.json"
[int]$nr2 = $nr -as [int] #Convert String to Int to convert 004 -> 4
$a = Get-Content $full_path -raw | ConvertFrom-Json
$a.value= "[`"E_" + $nr2 + "`"]"
$a | ConvertTo-Json | set-content $full_path -Force
}
Only excuting "[`"E_" + $nr2 + "`"]" returns the value I need.
For example if $nr2 = 145 it returns in ps console
["E_145"]
But my JSON looks like this:
{
"value": "[\"E_145\"]"
}
Why is powershell adding \ to my string?
How can I prevent powershell adding \ to my string?
You are mixing Json by hand and Json by ConvertTo-Json.
Powershell is doing javascript escaping of the backslashes you insert. Just set $a.value like this:
$a.value= #("E_$nr2")
That will create an array and the Json conversion will do the rest for you.
EDIT:
Here is a proof of concept:
$a = [pscustomobject]#{
value = 'Something else'
}
$nr2 = 145
$a.value= #("E_$nr2")
$a | ConvertTo-Json
outputs:
{
"value": [
"E_145"
]
}

How to write a value in json file using if conditions in powershell?

I am trying to add value in key pair json file using Powershell. I am getting an error. Need some guidance on PS Scripting.
Powershell 5.1 version and json file with key pair inside it.
MYJSON File:
{ "Theme":{"Res_List": {
"Method": "POST",
"Name":""}}}
PowerShell Script:
$file_path="C:\Users\RelativeConfig.json"
$json = Get-Content $file_path | Out-String | ConvertFrom-Json
$timestamp = Get-Date -Format ddMMHHmm
$namevalue = 'resource'+$timestamp+'e3'
echo $namevalue ##prints resource16sep2019 I want this to write in json as value for Name Key
$files = $json | Get-Member -MemberType Properties | Select-Object - ExpandProperty Name
$result = Foreach ($file in $json)
{
if ($file.Name -eq "Name") { $file.Value = $namevalue}
}
$result | ConvertTo-Json | Set-Content $json
Error:
No error but json is not updated with new values.
Expected:
{ "Theme":{"Res_List": {
"Method": "POST",
"Name":"resource16sep2019 "}}}
Actual:
{ "Theme":{"Res_List": {
"Method": "POST",
"Name":""}}}
To update your value in json you can do something like below
$bucket_name = "resource16sep2019" ## I want this to write in json as value for Name Key
$json.Theme.Res_List.Name = $bucket_name
It will directly replace the $bucket_name value with the Name value in JSON.
If you want to write this to the respective file use the below command,
$json | ConvertTo-Json -depth 32| set-content $file_path
Hope it helps! Cheers

Find and Replace Nested JSON Values with Powershell

I have an appsettings.json file that I would like to transform with a PowerShell script in a VSTS release pipeline PowerShell task. (BTW I'm deploying a netstandard 2 Api to IIS). The JSON is structured like the following:
{
"Foo": {
"BaseUrl": "http://foo.url.com",
"UrlKey": "12345"
},
"Bar": {
"BaseUrl": "http://bar.url.com"
},
"Blee": {
"BaseUrl": "http://blee.url.com"
}
}
I want to replace BaseUrl and, if it exists, the UrlKey values in each section which are Foo, Bar and Blee. (Foo:BaseUrl, Foo:UrlKey, Bar:BaseUrl, etc.)
I'm using the following JSON structure to hold the new values:
{
"##{FooUrl}":"$(FooUrl)",
"##{FooUrlKey}":"$(FooUrlKey)",
"##{BarUrl}":"$(BarUrl)",
"##{BleeUrl}":"$(BleeUrl)"
}
So far I have the following script:
# Get file path
$filePath = "C:\mywebsite\appsettings.json"
# Parse JSON object from string
$jsonString = "$(MyReplacementVariablesJson)"
$jsonObject = ConvertFrom-Json $jsonString
# Convert JSON replacement variables object to HashTable
$hashTable = #{}
foreach ($property in $jsonObject.PSObject.Properties) {
$hashTable[$property.Name] = $property.Value
}
# Here's where I need some help
# Perform variable replacements
foreach ($key in $hashTable.Keys) {
$sourceFile = Get-Content $filePath
$sourceFile -replace $key, $hashTable[$key] | Set-Content $filePath
Write-Host 'Replaced key' $key 'with value' $hashTable[$key] 'in' $filePath
}
Why are you defining your replacement values as a JSON string? That's just going to make your life more miserable. If you're defining the values in your script anyway just define them as hashtables right away:
$newUrls = #{
'Foo' = 'http://newfoo.example.com'
'Bar' = 'http://newbaz.example.com'
'Blee' = 'http://newblee.example.com'
}
$newKeys = #{
'Foo' = '67890'
}
Even if you wanted to read them from a file you could make that file a PowerShell script containing those hashtables and dot-source it. Or at least define the values as lists of key=value lines in text files, which can easily be turned into hashtables:
$newUrls = Get-Content 'new_urls.txt' | Out-String | ConvertFrom-StringData
$newKeys = Get-Content 'new_keys.txt' | Out-String | ConvertFrom-StringData
Then iterate over the top-level properties of your input JSON data and replace the nested properties with the new values:
$json = Get-Content $filePath | Out-String | ConvertFrom-Json
foreach ($name in $json.PSObject.Properties) {
$json.$name.BaseUrl = $newUrls[$name]
if ($newKeys.ContainsKey($name)) {
$json.$name.UrlKey = $newKeys[$name]
}
}
$json | ConvertTo-Json | Set-Content $filePath
Note that if your actual JSON data has more than 2 levels of hierarchy you'll need to tell ConvertTo-Json via the parameter -Depth how many levels it's supposed to convert.
Side note: piping the Get-Content output through Out-String is required because ConvertFrom-Json expects JSON input as a single string, and using Out-String makes the code work with all PowerShell versions. If you have PowerShell v3 or newer you can simplify the code a little by replacing Get-Content | Out-String with Get-Content -Raw.
Thank you, Ansgar for your detailed answer, which helped me a great deal. Ultimately, after having no luck iterating over the top-level properties of my input JSON data, I settled on the following code:
$json = (Get-Content -Path $filePath) | ConvertFrom-Json
$json.Foo.BaseUrl = $newUrls["Foo"]
$json.Bar.BaseUrl = $newUrls["Bar"]
$json.Blee.BaseUrl = $newUrls["Blee"]
$json.Foo.Key = $newKeys["Foo"]
$json | ConvertTo-Json | Set-Content $filePath
I hope this can help someone else.
To update values of keys at varying depth in the json/config file, you can pass in the key name using "." between the levels, e.g. AppSettings.Setting.Third to represent:
{
AppSettings = {
Setting = {
Third = "value I want to update"
}
}
}
To set the value for multiple settings, you can do something like this:
$file = "c:\temp\appSettings.json"
# define keys and values in hash table
$settings = #{
"AppSettings.SettingOne" = "1st value"
"AppSettings.SettingTwo" = "2nd value"
"AppSettings.SettingThree" = "3rd value"
"AppSettings.SettingThree.A" = "A under 3rd"
"AppSettings.SettingThree.B" = "B under 3rd"
"AppSettings.SettingThree.B.X" = "Z under B under 3rd"
"AppSettings.SettingThree.B.Y" = "Y under B under 3rd"
}
# read config file
$data = Get-Content $file -Raw | ConvertFrom-Json
# loop through settings
$settings.GetEnumerator() | ForEach-Object {
$key = $_.Key
$value = $_.Value
$command = "`$data.$key = $value"
Write-Verbose $command
# update value of object property
Invoke-Expression -Command $command
}
$data | ConvertTo-Json -Depth 10 | Out-File $file -Encoding "UTF8"