Trouble pasring nested values from json files using powershell - json

Trying to pull the signing_certificate_id field from the below json snippet, but unfortunately, the data is not making it into the excel export. The other info is making it into the csv. (there are cases where these code blocks exist twice in the same json to represent a separate environment.
Json Snippet:
{
"sfg_ping::production::standard_sp_connections": [
{
"name": "hhhh",
"entity_id": "https://hhhh.hhhh.com",
"contact_info": "hhhh#hhhh.com",
"sp_endpoint": "https://hhhh.hhhh.com/",
"sso_initialization_and_signature_policy": {
"sign_assertion_or_response": "assertion",
"sp_trust_model": "unanchored",
"signing_certificate_id": "gggggg",
"sp_initiated": {
"require_signed_authn_requests": false
}
},
Script being used:
Get-ChildItem "C:\Users\hhhh\appdev\targetfolder-json2" -Filter *.json -PipelineVariable file | ForEach-Object {
(Get-Content $_.pspath -Raw | ConvertFrom-Json).PSObject.Properties.Value | Select-Object #(
#{ l = 'filename'; e = { $file.Name }}, 'Name','contact_info', 'signing_certificate_id'
)
} | Export-Csv path\to\myexport.csv -NoTypeInformation

You need to create a calculated property for getting the nested JSON property, similar to what you did for filename:
Get-ChildItem "C:\Users\hhhh\appdev\targetfolder-json2" -Filter *.json -PipelineVariable file | ForEach-Object {
(Get-Content $_.pspath -Raw | ConvertFrom-Json).PSObject.Properties.Value | Select-Object #(
#{ l = 'filename'; e = { $file.Name }}, 'Name','contact_info',
#{ l = 'signing_certificate_id'; e = { $_.sso_initialization_and_signature_policy.signing_certificate_id }}
)
} | Export-Csv path\to\myexport.csv -NoTypeInformation

Related

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"
]
}

Powershell - Reading multiple json files in a directory and output the data

I'm having to whip up a process that will read multiple json files created by another process.
I have code that can read a single file, but we're needing to process these results in bulk.
Here's my current code:
$json = Get-ChildItem $filePath -recurse | Where-Object { $_.LastWriteTime -gt [DateTime] $filesNewerThan } | ConvertFrom-Json
$json.delegates | foreach-Object {
foreach ($File in $_.files)
{
[PSCustomObject]#{
LastName = $_.lastName
ZipCode = $File.zipCode
BirthDate = $File.birthdate
Address = $File.Address}
}
}
Right now I'm getting an error about an "invalid JSON primitive" which what I'm guessing is an issue where I don't have "Get-Content" specified in my code.
Wondering what my issue is with my code.
ConvertFrom-Json currently (as of PowerShell 7.0) doesn't support file-path input, only file-content input (the actual JSON string), which means that you need to involve Get-Content:
$json = Get-ChildItem -File $filePath -Recurse |
Where-Object { $_.LastWriteTime -gt [DateTime] $filesNewerThan } |
ForEach-Object { Get-Content -Raw -LiteralPath $_.FullName | ConvertFrom-Json }

Modifying JSON file using data from CSV in PowerShell

I'm trying to modify some specific values in a .json file based on two columns in a .csv file. If the current value in the .json file is identical to the one in the left column, I want to change it to the one in the right column.
This is my first time with PowerShell though, so I'm struggling to figure out how to go about doing this. I feel like my solution is not only wrong, but is using a double for loop when it might not need to. Here's what I have so far.
$jsonData = Get-Content -Path $jsonFile | ConvertFrom-Json
$csvData = Get-Content -Path $csvFile | Select-Object -Skip 1 # Skipping the header
foreach ($jsonItem in $jsonData.'Placeable List') {
foreach ($csvRow in $csvData) {
$splitRow = $csvRow -split ","
$lCol = $splitRow[0]
$rCol = $splitRow[1]
$currentItem = $jsonItem.'value'.'Appearance'.'value'
if ($currentItem -eq $lCol) {
$currentItem -eq $rCol
}
}
}
I managed to figure it out.
$csvData = Get-Content -Path $csvFile | Select-Object -Skip 1 # Skipping the header
$jsonData = Get-Content -Path $jsonFile -raw | ConvertFrom-Json
foreach($csvRow in $csvData) {
$splitRow = $csvRow -split ","
$lCol = $splitRow[0]
$rCol = $splitRow[1]
foreach($item in $jsonData.'Placeable List'.value) {
$item.Appearance | % {
if ($_.value -eq $lCol) {
$_.value = $rCol
}
}
}
}
$jsonData | ConvertTo-Json -depth 32 | Set-Content $jsonFile

Access Object From JSON File in Powershell

I have a JSON file that I am reading in Powershell. The structure of the file is below.
[
["computer1", ["program1", versionX]],
["computer2", ["program2", versionY]],
["computer3", ["program3", "versionX"],
["program1", "versionZ"]
],
]
What I want in the program is use $env:computername and compare it with the computerX in the JSON file. If found a match, then iterate through and get the values of programName and ProgramVersion.
However, I don't know how to search through the objects and find ALL items under that.
This is what I have so far.
$rawData = Get-Content -Raw -Path "file.json" | ConvertFrom-Json
$computername=$env:computername
$data = $rawData -match $computername
This gives me objects under it. But how do I iterate through and get individual values?
But don't know what I do after that.
To start you need to be using a valid JSON file
{
"computer1": {
"program1": "versionX"
},
"computer2": {
"program2": "versionY"
},
"computer3": {
"program3": "versionX",
"program1": "versionZ"
}
}
Then you can access the PSObject Properties
$rawData = Get-Content -Raw -Path "file.json" | ConvertFrom-Json
$rawData.PsObject.Properties |
Select-Object -ExpandProperty Name |
ForEach-Object { IF ($_ -eq $env:COMPUTERNAME) {
Write-Host "Computer Name : " $_
Write-Host "Value : " $rawData."$_"
}
}
EDIT for Computer, Program, and Version as separate values
psobject.Properties.Name will give all the program names.
psobject.Properties.Name[0] will give the first program name.
psobject.Properties.value[0] will give the first program version value.
You need to increment the value to get second value, you can also use -1 as a shortcut for the last value.
$rawData = Get-Content -Raw -Path "file.json" | ConvertFrom-Json
$rawData.PsObject.Properties |
Select-Object -ExpandProperty Name |
ForEach-Object { IF ($_ -eq $env:COMPUTERNAME) {
$Computer = $_
$Values = $rawData.$_
}
}
$Computer
$Values.psobject.Properties
$Values.psobject.Properties.Name
$Values.psobject.Properties.Name[0]
$Values.psobject.Properties.value[0]
$Values.psobject.Properties.Name[1]
$Values.psobject.Properties.value[1]
You could also use the program name
$Values.program1
$Values.program2
$Values.program3