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
Related
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
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 }
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
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