Adjust json file using ConvertFrom-Json - json

I have a json file with the following content
{
"name":"myApp",
"version":"1"
}
I would like to use Powershell to read this json file, adjust the version number, then output the new json to the same file.
I currently have this, but it doesn't work and only outputs an empty file
Get-Content file.json | ConvertFrom-Json | ForEach{$_.version = "2"} | ConvertTo-Json | Out-File file.json -Encoding ascii
I am getting stuck on how to update values on the Json object created by ConvertFrom-Json and pipe this back into ConvertTo-Json
I would like to do this all in one line if possible.

Once you assign the JSON to an object, you should be able to change it from there then write it to a file (if desired).
Create JSON object from file contents:
$jsonObject = Get-Content file.json -Raw | ConvertFrom-Json
Change the current object. In your example the "version" property:
#update object
$jsonObject| %{$_.version = "2"}
Write object to file:
$jsonObject | ConvertTo-Json | Out-File "file.json" -Encoding ascii

Related

How to remove an object from a JSON file in PowerShell

I am trying to remove an object from a JSON file using PowerShell.
I read in a JSON file that has some objects in it (C:\eventStaging.json = [{"server_name":"server1","date":"2021-08-13","user":"user1"},{"server_name":"server2","date":"2021-08-13","user":"user2"}] )
The plan is to loop through each object, add that object to another json file (C:\scheduledEvent.json) and then remove that same object from where it came from (C:\eventStaging.json).
Adding each object to a different json file is easy enough. Here is what I have:
$json = Get-Content 'C:\eventStaging.json' | Out-String | ConvertFrom-Json
foreach ($j in $json){
$EventStart = Get-Content 'C:\scheduledEventStart.json' | Out-String | ConvertFrom-Json
$eventStartList += $EventStart
$eventStartList += $j
$eventStartList | ConvertTo-Json -depth 100 | Out-File 'C:\scheduledEventStart.json'
}
My problem is removing the object $j from eventStaging.json.
I have tried:
$removeStaging = Get-Content 'C:\eventStaging.json' | Out-String | ConvertFrom-Json
$removeStaging.PSObject.Properties.Remove($j)
$removeStaging | ConvertTo-Json -depth 100 | Out-File 'C:\eventStaging.json' -Force
but $removeStaging is storing nothing.
I also tried:
[System.Collections.ArrayList]$removeStaging = Get-Content 'C:\eventStaging.json' | Out-String | ConvertFrom-Json
$newStaging = $removeStaging.Remove($j)
$newStaging | ConvertTo-Json -depth 100 | Out-File 'C:\eventStaging.json'
but again, $newStaging stores nothing..
Has anyone any guidance on this please?
If you have access to PowerShell Core, you can use ConvertFrom-Json -AsHashTable when removing the scheduled event from eventStaging.json to make this a bit easier:
$removeStaging = Get-Content -Raw 'C:\eventStaging.json' | ConvertFrom-Json -AsHashTable
$removeStaging.Remove($j)
$removeStaging | ConvertTo-Json -depth 100 | Out-File 'C:\eventStaging.json' -Force
With Windows PowerShell, your final attempt with the ArrayList conversion should have worked, assuming you are trying to remove a top-level element and not a sub-property of the element. Testing with the following code shows my json file is updated with the removed element:
# Create test json file
#{Name = 'Bender'; Age = 99}, #{Name = 'Dean'; Age = 98} | ConvertTo-Json | Out-File test.json
# Import JSON as ArrayList of PSCustomObjects
[System.Collections.ArrayList]$obj = Get-Content -Raw test.json | ConvertFrom-Json
# Remove one of the objects by reference
$obj.Remove($obj[1])
# Write the JSON to file, it will only have the one entry in it
$obj | ConvertTo-Json | Out-File test.json
If you update your question with a more complete sample of this area I can evaluate further but either of the above approaches should work.
Additionally, note I've removed your use of Out-String and instead used Get-Content -Raw. The -Raw parameter tells Get-Content to parse the file as a literal string instead of returning a collection of single-lines.

Powershell convertto-json gives a bad format

Hello I'm trying to use convertto-json to create a json file from another output and save it but I'm getting a bad json format
Here is my function
$output.value | ForEach-Object {
"{"+"id"+':'+ $_.id+','+"outcome" +':'+ '"'+$_.results.outcome+'"'+','+"idtc"+':' +$_.testCaseReference.id + "}"
} | ConvertTo-Json| Out-File -FilePath .\tfs.json
Here is the outcome of the tfs.json
[
"{id:11431,outcome:\"passed\",idtc:70155}",
"{id:11432,outcome:\"unspecified\",idtc:70156}",
"{id:11433,outcome:\"failed\",idtc:70157}",
"{id:11434,outcome:\"unspecified\",idtc:70158}"
]
Can anyone help why it does appear in that way instead of
[
{"id":11431,"outcome":"passed","idtc":70155"},
{"id":11432,"outcome":"unspecified","idtc":70156"},
{"id":11433,"outcome":"failed","idtc":70157"},
{"id":11434,"outcome":"unspecified","idtc":70158"}
]
The output you're receiving from ConvertTo-JSON is pretty much expected. You're passing a string to the cmdlet hence it is returning a string as JSON.
Try this instead:
$output.value | ForEach-Object {
[pscustomobject]#{
id = $_.id
outcome = $_.results.outcome
idtc = $_.testCaseReference.id
}
} | ConvertTo-Json | Out-File -FilePath .\tfs.json

Replace content by key in JSON

I've the JSON file with the following structure:
{
"Url": "placeholder",
}
I'd like to write a Powershell script which replaces the value ("placeholder") by key ("Url").
I know how to replace content by I don't know how to save it back to the file.
$snapshot = (Get-Content settings.json | ConvertFrom-Json)
$snapshot.Url = "Test"
You can write it back using the Set-Content cmdlet. E. g.:
$snapshot | ConvertTo-Json | Set-Content

JSON formatting, either from file or variable

I have a PS script, which get JSON in variable ant then saves it in file.
Unfortunately, it get value in one string, like this:
{ "persistentdataapi": "https://somevalue.azurewebsites.net/", "collectioncountapi": "https://anothervalue.azurewebsites.net/", "eventserviceapi": "https://thirdvalue.azurewebsites.net/", "securityserviceapi": "https://fourthvalue.azurewebsites.net/" }
Is there any way, to process this value through some (preferably PS) JSON formatting, to get this one:
{
"persistentdataapi": "https://somevalue.azurewebsites.net/",
"collectioncountapi": "https://anothervalue.azurewebsites.net/",
"eventserviceapi": "https://thirdvalue.azurewebsites.net/",
"securityserviceapi": "https://fourthvalue.azurewebsites.net/",
}
Code to get value in Jenkins:
Import-Module "C:\Program Files\WindowsPowerShell\Modules\Octopus-Cmdlets\0.4.4\Octopus-Cmdlets.psd1"
connect-octoserver http://internal-Octopus.azure.com:8082 API-123456789012345678
$raw = (Get-OctoVariable var.Portal.Web DataAPIJson | Where-Object { $_.Environment -eq "QA" } )
$raw.Value | Out-File "$env:WORKSPACE\portal\var.Portal.Web\dataapi.json"
Powershell by default pretty-prints any JSON it produces.
So the correct way to do pretty-printing is to parse the JSON string into an object, and immediately convert it back to a JSON string.
$json = '{ "persistentdataapi": "https://somevalue.azurewebsites.net/", "collectioncountapi": "https://anothervalue.azurewebsites.net/", "eventserviceapi": "https://thirdvalue.azurewebsites.net/", "securityserviceapi": "https://fourthvalue.azurewebsites.net/" }'
$json | ConvertFrom-Json | ConvertTo-Json
produces
{
"persistentdataapi": "https://somevalue.azurewebsites.net/",
"collectioncountapi": "https://anothervalue.azurewebsites.net/",
"eventserviceapi": "https://thirdvalue.azurewebsites.net/",
"securityserviceapi": "https://fourthvalue.azurewebsites.net/"
}
or in your case
$file = "$env:WORKSPACE\portal\var.Portal.Web\dataapi.json"
$raw.Value | ConvertFrom-Json | ConvertTo-Json | Out-File $file -Encoding UTF8
As a side-effect this also makes sure that the JSON in the file is valid, because otherwise ConvertFrom-Json will throw an error.
Please always explicitly specify UTF8 encoding when reading and writing JSON files.
$data = Get-Content $file -Encoding UTF8 | ConvertFrom-Json
$data | ConvertTo-Json | Set-Content $file -Encoding UTF8
The reason for that is
By widely-accepted convention, JSON files ought to be UTF8.
Unless specified otherwise, Get-Content and Set-Content will use the system's default encoding to read/write text files.
The system default is very seldom UTF-8, most of the time it will be a legacy single-byte encoding like Windows-1252.
This creates the risk of
mangling Unicode characters, which are legal in JSON, when reading a JSON file.
creating JSON files that are not UTF-8, making them hard to consume by others.
In fact, always specify an encoding explicitly when working with text files, not only in the case of JSON.

Replace only first occurrence

I have a PowerShell scripts which replaces
"version" : "xxx"
with
"version" : "myBuildNumber"
Now I encountered that I have multiple of these in my file.
I only want to replace the first occurrence.
I tried already Powershell - Replace first occurrences of String but it does not work with my regex.
Here's my script:
(Get-Content myFile.txt) -replace '(?<pre>"version"[\s]*:[\s]*)(?<V>"[^\"]*")', "`$1`"$Env:BUILD_VERSION`"" | Out-File myFile.txt
Since you are patching a JSON file, regex isn't the way to go. Instead you should parse the JSON, access and change the property you want and write it back:
$filePath = 'your_Path_To_project.json'
$json = (Get-Content $filePath -raw | ConvertFrom-Json)
$json.version = $Env:BUILD_VERSION
$json | ConvertTo-Json -Depth 10 | Set-Content $filePath