How to remove an object from a JSON file in PowerShell - json

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.

Related

Adjust json file using ConvertFrom-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

Powershell ConvertFrom-Json accessing json value

I have a json file that I'd like to convert to csv. However, the actual value is nested inside reading key that I need to access. It returns System.Object[] in which I know I have to access this, but I don't know how.
the following is the result.json file,
{"totalNumberOfReadings":1488,
"readings":
[
{"meterNumber":"xxxxx","date":"2022-02-01 00:00","reading":0.0,"status":"AsRequested"},
{"meterNumber":"xxxxx","date":"2022-01-31 23:30","reading":0.0,"status":"As Requested"},
{"meterNumber":"xxxxx","date":"2022-01-31 23:00","reading":0.0,"status":"As Requested"},
{"meterNumber":"xxxxx","date":"2022-01-31 23:00","reading":0.0,"status":"As Requested"},
]
}
My script is like this
C:\> (Get-Content -Raw result.json | ConvertFrom-Json) | ConvertTo-Csv -NoTypeInformation
the output is this
"totalNumberOfReadings","readings"
"1488","System.Object[]"
This is just the summary/metadata. I want the actual content inside the key's value, how to access the value?
Either use member access:
(Get-Content -Raw result.json | ConvertFrom-Json).readings | ConvertTo-Csv -NoTypeInformation
...or only pipeline commands:
Get-Content -Raw result.json | ConvertFrom-Json | ForEach-Object readings | ConvertTo-Csv -NoTypeInformation
ForEach-Object readings is the short form of ForEach-Object -MemberName readings.

Azure extension error while calling PowerShell script

Using PowerShell, I am trying to encode text file to a string and encoded string is provided as input to get cook book name and recipe details. When I check the output cookbook name and Json file, they are string and valid json file. But when I use this code via Azure extension, I get error -
message:
ConvertFrom-Json : Unterminated string passed in.
FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
#Encode the Input file
[string]$sStringToEncode=Get-Content "c:\temp\json.txt"
$sEncodedString=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sStringToEncode))
write-host -ForegroundColor Green "Encoded String:`n" $sEncodedString
#Decode text
$EncodedText = $sEncodedString.replace("\n","")
write-host "String after replacing \n:" $EncodedText
$DecodedText = [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($EncodedText))
#Convert to Json file
$DecodedText | ConvertFrom-Json | ConvertTo-Json | Out-File c:\temp\DNAFiledata.json
#Taking out cookbook Name
$CookbookName = (Get-Content c:\temp\DNAFiledata.json | Out-String | ConvertFrom-Json).cookbook_name
$CookbookName | Out-File "c:\temp\3_CookBookName.txt"
#Taking out recipe details
$Datainput = (Get-Content -Raw -Path c:\temp\DNAFiledata.json | ConvertFrom-Json).chef_attributes | ConvertTo-Json
$Datainput | Out-File "c:\temp\4_Datainput.json"
$Datainput | Set-Content "c:\temp\$CookbookName.json"
Any suggestions on this please.

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 }

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