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
Related
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
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
Given a custom powershell object (bar) that is created from json (foo.json)
How would you sort the object alphabetically by key?
foo.json
{
"bbb": {"zebras": "fast"},
"ccc": {},
"aaa": {"apples": "good"}
}
Desired output
foo.json
{
"aaa": {"apples": "good"},
"bbb": {"zebras": "fast"},
"ccc": {}
}
Example
$bar = get-content -raw foo.json | ConvertFrom-Json
$bar.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PSCustomObject System.Object
I've tried the following using sort-object
$bar = $bar | Sort
$bar = $bar | Sort-Object
Sort-Object -InputObject $bar
Sort-Object -InputObject $bar -Property Name
Sort-Object -InputObject $bar -Property #{Expression="Name"}
Sort-Object -InputObject $bar -Property #{Expression={$_.PSObject.Properties.Name}}
I've also tried converting the PSObject to a hashtable (hashtables appear to automatically sort based on name), then convert that hashtable back to json, but it looses the order again.
$buzz = #{}
$bar.psobject.properties |Foreach { $buzz[$_.Name] = $_.Value }
ConvertTo-Json $buzz -Depth 9
Update
Changed foo.json to include values aswell as keys
As Mathias R. Jessen notes, there is no collection to sort here, just a single object whose properties you want to sort, so you need reflection via Get-Member to obtain the object's properties:
$bar = get-content -raw foo.json | ConvertFrom-Json
# Build an ordered hashtable of the property-value pairs.
$sortedProps = [ordered] #{}
Get-Member -Type NoteProperty -InputObject $bar | Sort-Object Name |
% { $sortedProps[$_.Name] = $bar.$($_.Name) }
# Create a new object that receives the sorted properties.
$barWithSortedProperties = New-Object PSCustomObject
Add-Member -InputObject $barWithSortedProperties -NotePropertyMembers $sortedProps
A more streamlined version that uses -pv (-PipelineVariable) to "cache" the unsorted custom object produced by ConvertFrom-Json:
$barSortedProps = New-Object PSCustomObject
Get-Content -Raw foo.json | ConvertFrom-Json -pv jo |
Get-Member -Type NoteProperty | Sort-Object Name | % {
Add-Member -InputObject $barSortedProps -Type NoteProperty `
-Name $_.Name -Value $jo.$($_.Name)
}
what about this:
Function Sort-PSObject {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$true)]$inputString
)
process {
($inputString | out-string).trim() -split "`r`n" | sort
}
}
Can send direct from pipeline
A combined version of #mklement0 and #EricWeintraub's answers:
Function Sort-PSObjectMembers {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$true)]$inputObj
)
process {
$sortedProps = [ordered] #{}
Get-Member -Type NoteProperty -InputObject $inputObj | Sort-Object Name | ForEach-Object { $sortedProps[$_.Name] = $inputObj.$($_.Name) }
# Create a new object that receives the sorted properties.
$sortedObj = New-Object PSCustomObject
Add-Member -InputObject $sortedObj -NotePropertyMembers $sortedProps
return $sortedObj
}
}
So you can use it like this:
$elements | Sort-PSObjectMembers | ConvertTo-Json -Depth 32 | Out-File "elements.json" -Encoding utf8
How do I loop through all items in a JSON file? The current code just writes all names on one big line:
Get-Content -Raw -Path c:\temp\Environments.Generic.json | ConvertFrom-Json | ForEach-Object {
Write-Host $_.Name
}
json file:
[
{
"Name":"EnableRetry",
"Description":"Enable retry for Webservice Task",
"Type":"Boolean",
"Sensitive":false,
"Value":true
},
{
"Name":"FolderStageFiles",
"Description":"Location of stage files",
"Type":"String",
"Sensitive":false,
"Value":"d:\\sources\\"
},
{
"Name":"FtpPassword",
"Description":"Secret FTP password",
"Type":"String",
"Sensitive":true,
"Value":"Welcome1"
}
]
I ended up Select-Object and a ForEach-Object:
$JSON = Get-Content -Raw -Path c:\temp\Environments.Generic.json | ConvertFrom-Json
$JSON | Select-Object -Property Name,Description,Type,Sensitive,Value | ForEach-Object {
Write-Host $_.Name $_.Value
}
If you do this:
$JSON = Get-Content -Raw -Path c:\temp\Environments.Generic.json | ConvertFrom-Json
$JSON will be a PowerShell object that contains a collection of objects with all of the properties defined in your JSON file.
Enter $JSON at the console and you'll see the contents of this object.
To access specific properties for specific items in the collection you could do (for example):
$JSON | Where {$_.Name -eq 'FolderStageFiles'} | Select -ExpandProperty Value
How do I parse the following JSON into hashtable in PowerShell? I want to pair car name ("BMW") as key and color ("Dark Gray") as value in the hashtable.
{
"Car": [
{"BMW": "Dark Gray"},
{"Audi": "Yellow"}
]
}
Like this:
$json = #'
{
"Car": [
{"BMW": "Dark Gray"},
{"Audi": "Yellow"}
]
}
'#
$ht = #{}
ConvertFrom-Json $json | Select-Object -Expand 'Car' | ForEach-Object {
$ht[$_.PSObject.Properties.Name] = $_.PSObject.Properties.Value
}
If you're stuck with PowerShell v2, but have at least .Net Framework 3.5 you could do something like this instead:
$json = #'
...
'#
$ht = #{}
[void][Reflection.Assembly]::LoadWithPartialName('System.Web.Extensions')
$serializer = New-Object Web.Script.Serialization.JavaScriptSerializer
$serializer.DeserializeObject($json).Values.GetEnumerator() |
ForEach-Object { $_ } |
ForEach-Object { $ht[($_.Keys -join '')] = ($_.Values -join '') }
If that also isn't possible, but your key/value pairs are always on one (separate) line, you could extract the data with a regular expression (although I wouldn't recommend that approach):
$json = #'
...
'#
$ht = #{}
$json -split "`n" | Where-Object {
$_ -match '\{"(.*?)": "(.*?)"\}'
} | ForEach-Object {
$ht[$matches[1]] = $matches[2]
}
Otherwise you'll have to write a JSON parser yourself.
In Powershell v6 it's built-in with ConvertFrom-Json:
$hashtable = '{ "key1":"value1", "key2":"value2" }' | ConvertFrom-Json -AsHashtable
For example:
PS> $hashtable["key1"]
value1