Manipulate JSON File with multiple objects using Powershell - json

I have a JSON File called index.json which looks like this :
{
"First": {
"href": "test/one two three.html",
"title": "title one"
},
"Second": {
"href": "test/test test/one two three four.html",
"title": "title two"
}
}
I want to write a powershell script to update the href of each object to replace the spaces with -.
The JSON file should looks like this:
{
"First": {
"href": "test/one-two-three.html",
"title": "title one"
},
"Second": {
"href": "test/test-test/one-two-three-four.html",
"title": "title two"
}
}
I got some help from this post:
Iterating through a JSON file PowerShell
I have already written a script to get all the href values, I dont know how to update the same in the original JSON file. My script looks like this:
function Get-ObjectMembers {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
[PSCustomObject]$obj
)
$obj | Get-Member -MemberType NoteProperty | ForEach-Object {
$key = $_.Name
[PSCustomObject]#{Key = $key; Value = $obj."$key"}
}
}
$a = Get-Content 'index.json' -raw | ConvertFrom-Json | Get-ObjectMembers
foreach($i in $a){
$i.Value.href.Replace(" ","-")
}

I've done it this way.
$path='index.json'
$Content= (Get-Content $path -raw | ConvertFrom-Json)
$memberNames=( $Content | Get-Member -MemberType NoteProperty).Name
foreach($memberName in $memberNames){
($Content.$memberName.href)=($Content.$memberName.href).Replace(" ","-")
}
$Content | ConvertTo-Json | Out-File $path -Append

Related

How to remove nested JSON object members

I'm trying to remove the length value pair from the following JSON file:
{
"uuid": "6f74b1ba-0d7c-4c85-955b-2a4309f0e8df",
"records": {
"record1": [
{
"locale": "en_US",
"category": "alpha",
"contents": "My hovercraft is full of eels",
"length": 29
}
],
"record2": [
{
"locale": "cs_CZ",
"category": "alpha",
"contents": "Moje vznášedlo je plné úhořů",
"length": 28
}
]
}
}
Even though the length property is apparently found, it's not deleted, because the output file is identical to the input file.
I'm using the following code:
$infile = "C:\Temp\input.json"
$outfile = "C:\Temp\output.json"
$json = Get-Content $infile -Encoding UTF8 | ConvertFrom-Json
$records = $json.records
$records.PSObject.Properties | ForEach-Object {
if (($_.Value | Get-Member -Name "length")) {
Write-Host "length property found."
$_.Value.PSObject.Properties.Remove("length")
}
}
$json | ConvertTo-Json -Depth 3 | Out-File $outfile -Encoding UTF8
What am I doing wrong?
The record* properties are arrays, so you need a nested loop to process them:
foreach( $property in $records.PSObject.Properties ) {
foreach( $recordItem in $property.Value ) {
if( $recordItem | Get-Member -Name 'length' ) {
$recordItem.PSObject.Properties.Remove( 'length' )
}
}
}
For code clarity and performance I've replaced the ForEach-Object command by the foreach statement. Especially in nested loops, foreach helps to improve clarity as we no longer have to think about the context of the automatic $_ variable. Also the foreach statement is faster as it doesn't involve pipeline overhead.

(Powershell) Read and change JSON value to a date

I'm trying to write a powershell script that could read a JSON, its extension is .pros, then change the project name from "test" to "test 12/12 13:24" or something similar. So far I was able to read it, but then I can't get to the project_name field.
my code:
$pros = Get-ChildItem -Path $house -Recurse -Include *.pros
$time = Get-Date -Format 'u'
$pog = Get-Content $pros -raw | ConvertFrom-Json
$pog.update | $_.project_name=$time
$pog | ConvertTo-Json -depth 32| set-content $pros
Write-Output $time
The .pros:
{
"py/object": "pros.conductor.project.Project",
"py/state": {
"project_name": "Marcos_Yuck_new",
"target": "v5",
"templates": {
"kernel": {
"location": "/home/dragon/.config/pros/templates/kernel#3.5.3",
"metadata": {

PowerShell Loop through nested json and remove property

I am getting some json data from a API, however I don't need most of this data. I am trying to remove some fields so that the when I save this data as a json file it isn't so large. I doesnt seem to be removing any of the fields I am trying to remove.
Code:
$Response = Invoke-RestMethod -Uri "https://mtgjson.com/api/v5/AllPrintings.json" -Method GET
$Obj = ConvertFrom-Json $Response
$Obj.PSObject.Properties.Remove('booster')
$Obj.PSObject.Properties.Remove('cards')
$Obj | ConvertTo-Json | Out-File ./All-Sets-Data.json -Force
Json:
{
"data": {
"10E": {
"baseSetSize": 383,
"block": "Core Set",
"booster": "#{default=}",
"cards": "",
"code": "10E",
...
},
"2ED": {
"baseSetSize": 302,
"block": "Core Set",
"booster": "#{default=}",
"cards": "",
"code": "2ED",
...
},
"2XM": {
"baseSetSize": 332,
"booster": "#{default=}",
"cards": "",
"code": "2XM",
...
},
...
}
}
$Obj.data.'10E'.PSObject.Properties.Remove('booster')
$Obj.data.'10E'.PSObject.Properties.Remove('cards')
$Obj.data.'2ED'.PSObject.Properties.Remove('booster')
# and so on
The above code snippet should work. However, you can do all in a one step by calling the following (recursive) function RemoveProperty:
Function RemoveProperty {
param (
# A PSCustomObject
[Parameter( Mandatory, ValueFromPipeline )] $Object,
# A list of property names to remove
[Parameter( Mandatory )] [string[]]$PropList,
# recurse?
[Parameter()] [Switch]$Recurse
)
# Write-Host $Object -ForegroundColor Cyan
foreach ( $Prop in $PropList ) {
$Object.PSObject.Properties.Remove($prop)
}
# Write-Host $Object -ForegroundColor Green
if ( $Recurse.IsPresent ) {
foreach ($ObjValue in $Object.PSObject.Properties.Value) {
# Write-Host $ObjValue -ForegroundColor Yellow
if ( $ObjValue.GetType().Name -eq 'PSCustomObject' ) {
$ObjValue | RemoveProperty -PropList $PropList -Recurse
}
}
}
}
# sample usage:
$Obj = ConvertFrom-Json $Response
RemoveProperty -Object $Obj -PropList 'booster','cards' -Recurse
$Obj | ConvertTo-Json | Out-File ./All-Sets-Data.json -Force
(Please note that the RemoveProperty function contains some Write-Host in commented lines; originally used used for debugging purposes).

Read one Value of a specific object from a json file

I want to return only the hash value of one object from my test.json file.
Right now, I am getting all hash values with my code.
json file:
[
{
"name": "abc.txt",
"hash": "D23FC7C4C9F1ED7CD147D7D29E3A541D"
},
{
"name": "def.txt",
"hash": "681B75B81734F7215C2DAD1F7EDFDAF7"
},
{
"name": "ghi.txt",
"hash": "81709CDC04EBDBDAA9BA15F6CAF1F05B"
},
{
"name": "xyz.txt",
"hash": "56F07815D06966FA3A73275797496881"
}
]
My code:
$jsonFile = $PSScriptRoot + "\test.json"
(Get-Content $jsonFile | ConvertFrom-Json | where {$_.name -eq 'abc.txt'}).hash
Careful with the parentheses:
((Get-Content $jsonFile | ConvertFrom-Json) | where {$_.name -eq "abc.txt"}).hash
#D23FC7C4C9F1ED7CD147D7D29E3A541D
Like this your json file contains a list of dictionaries. First you need to select which item of your list you want to have and then you can retrieve the value based on the key.
Try something like this:
$jsonFile = $PSScriptRoot + "\test.json"
$jsonList = Get-Content $jsonFile | ConvertFrom-Json
$jsonList[0].hash
Alternatively:
$jsonObject = $jsonList | Where-Object {$_.name -eq 'abc.txt'} | Select-Object hash

PowerShell : retrieve JSON object by field value

Consider JSON in this format :
"Stuffs": [
{
"Name": "Darts",
"Type": "Fun Stuff"
},
{
"Name": "Clean Toilet",
"Type": "Boring Stuff"
}
]
In PowerShell 3, we can obtain a list of Stuffs :
$JSON = Get-Content $jsonConfigFile | Out-String | ConvertFrom-Json
Assuming we don't know the exact contents of the list, including the ordering of the objects, how can we retrieve the object(s) with a specific value for the Name field ?
Brute force, we could iterate through the list :
foreach( $Stuff in $JSON.Stuffs ) {
But I am hopeful there exists a more direct mechanism ( similar to Lync or Lambda expressions in C# ).
$json = #"
{
"Stuffs":
[
{
"Name": "Darts",
"Type": "Fun Stuff"
},
{
"Name": "Clean Toilet",
"Type": "Boring Stuff"
}
]
}
"#
$x = $json | ConvertFrom-Json
$x.Stuffs[0] # access to Darts
$x.Stuffs[1] # access to Clean Toilet
$darts = $x.Stuffs | where { $_.Name -eq "Darts" } #Darts
I just asked the same question here: https://stackoverflow.com/a/23062370/3532136
It has a good solution. I hope it helps ^^.
In resume, you can use this:
The Json file in my case was called jsonfile.json:
{
"CARD_MODEL_TITLE": "OWNER'S MANUAL",
"CARD_MODEL_SUBTITLE": "Configure your download",
"CARD_MODEL_SELECT": "Select Model",
"CARD_LANG_TITLE": "Select Language",
"CARD_LANG_DEVICE_LANG": "Your device",
"CARD_YEAR_TITLE": "Select Model Year",
"CARD_YEAR_LATEST": "(Latest)",
"STEPS_MODEL": "Model",
"STEPS_LANGUAGE": "Language",
"STEPS_YEAR": "Model Year",
"BUTTON_BACK": "Back",
"BUTTON_NEXT": "Next",
"BUTTON_CLOSE": "Close"
}
Code:
$json = (Get-Content "jsonfile.json" -Raw) | ConvertFrom-Json
$json.psobject.properties.name
Output:
CARD_MODEL_TITLE
CARD_MODEL_SUBTITLE
CARD_MODEL_SELECT
CARD_LANG_TITLE
CARD_LANG_DEVICE_LANG
CARD_YEAR_TITLE
CARD_YEAR_LATEST
STEPS_MODEL
STEPS_LANGUAGE
STEPS_YEAR
BUTTON_BACK
BUTTON_NEXT
BUTTON_CLOSE
Thanks to mjolinor.
David Brabant's answer led me to what I needed, with this addition:
x.Stuffs | where { $_.Name -eq "Darts" } | Select -ExpandProperty Type
Hows about this:
$json=Get-Content -Raw -Path 'my.json' | Out-String | ConvertFrom-Json
$foo="TheVariableYourUsingToSelectSomething"
$json.SomePathYouKnow.psobject.properties.Where({$_.name -eq $foo}).value
which would select from json structured
{"SomePathYouKnow":{"TheVariableYourUsingToSelectSomething": "Tada!"}
This is based on this accessing values in powershell SO question
. Isn't powershell fabulous!
In regards to PowerShell 5.1 ...
Operating off the assumption that we have a file named jsonConfigFile.json with the following content from your post:
{
"Stuffs": [
{
"Name": "Darts",
"Type": "Fun Stuff"
},
{
"Name": "Clean Toilet",
"Type": "Boring Stuff"
}
]
}
This will create an ordered hashtable from a JSON file to help make retrieval easier:
$json = [ordered]#{}
(Get-Content "jsonConfigFile.json" -Raw | ConvertFrom-Json).PSObject.Properties |
ForEach-Object { $json[$_.Name] = $_.Value }
$json.Stuffs will list a nice hashtable, but it gets a little more complicated from here. Say you want the Type key's value associated with the Clean Toilet key, you would retrieve it like this:
$json.Stuffs.Where({$_.Name -eq "Clean Toilet"}).Type
It's a pain in the ass, but if your goal is to use JSON on a barebones Windows 10 installation, this is the best way to do it as far as I've found.
This is my json data:
[
{
"name":"Test",
"value":"TestValue"
},
{
"name":"Test",
"value":"TestValue"
}
]
Powershell script:
$data = Get-Content "Path to json file" | Out-String | ConvertFrom-Json
foreach ($line in $data) {
$line.name
}