Search code examples
jsonpowershellpowershell-cmdlet

Replace a value in a JSON file using Powershell


How can I replace a value in a JSON file with another value taken from a config file (JSON)? This is the code for the JSON files:

Config.json

{
    "ABlob_AAD_Snapshot": [
    {
      "name": "properties.availability.frequency",
      "value": "$Frequency$"
    }]       
}

ABlob_AAD_Snapshot.json

{
  "name": "AzureBlobStore",
  "properties": {
                 "type": "AzureStorage",
                 "availability": {
                                 "frequency": "Value from Config.json file"
                                 }
                 }
}

What I'm trying to do is the following:

  1. Go through the Config.json file and store the values for "name" and "value" segments in variables. The "name" segment value is a path in ABlob_AAD_Snapshot.json file.
  2. Follow the path in the ABlob_AAD_Snapshot.json file and replace the segment "frequency" with the value of segment "value" ($frequency$)

After this process, the ABlob_AAD_Snapshot.json should look like this:

{
  "name": "AzureBlobStore",
  "properties": {
                 "type": "AzureStorage",
                 "availability": {
                                 "frequency": "$frequency$"
                                 }
                 }
}

The problem here is that my original config.json file has more than one array (which represents file names) so I will parse more than one file and the value for "name" segment will not always be the same I mean, in this case, the value (or path) is properties.availability.frequency but it could be properties.activities.scheduler.interval or properties.activities.typeProperties.extendedProperties.WebAppClientID.

So as you can see the name and the quantity of "nodes" could change.

This is my PowerShell script:

    $ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition 

#path to config file
$ConfigFile = "$ScriptPath\ParameterConfigOriginal.json"

#Convert the json file to PSObject
$json = Get-Content $ConfigFile | Out-String | ConvertFrom-Json


#Get all the arrays (files) in Conifg.json
$files = $json | Get-Member -MemberType Properties | Select-Object -ExpandProperty Name

#Go through all the arrays (files)
Foreach($file in $files)
{
   if( $file -eq '$schema') {continue}

    #store the path of the file to be modified
    $FileName = $file + ".json"
    $FilePath = "$ScriptPath\LinkedServices\" + $FileName"

   #Go through all the elements of the arrray
   Foreach($item in $json.$file)
   {
     #Store the path 
     $name = $item.name


    #Store the value
    $value = $item.value

    #Convert the file to be modified to PSObject
    $file = Get-Content $FilePath | Out-String | ConvertFrom-Json  

    #======STUCK IN HERE=============
    # How can dynamically navigate through the file nodes like this?

    $file.properties.availability.frequency

    #and set the corresponding value

    $file.properties.availability.frequency = $value

   }
}

I'm new in the PowerShell world and I don't know if there is a cmdlet that helps me to do what I need.

Any suggestion will be appreciated.

EDIT

Simple Path

$snapshot.properties.availability.frequency

Path with arrays

$snapshot.properties.activities[0].scheduler.frequency

this is an example of the JSON file with arrays Destination file

and this is the result Destination file updated

Any idea on what could be happening?


Solution

  • Invoke-Expression will help you.

    #Go through all the arrays (files)
    Foreach($file in $files)
    {
        $snapshot = (Get-Content ("./" + $file + ".json") | ConvertFrom-Json)
    
        # get config corresponds to the $file
        $config = Invoke-Expression ('$json.' + $file)
    
        # set value according to the config
        Invoke-Expression ('$snapshot.' + $config.name + "='" + $config.value + "'")
    
        # $snapshot.properties.availability.frequency
        # -> $Frequency$
    }
    

    Edit

    You have to use ConvertTo-Json -Depth 100 to write the result to JSON file properly (specify the appropriate depth according to your JSON files.). Without -Depth option, you will get the result like "@{type=Copy, typeProperties=;, ...}".