Search code examples
jsonpowershell

How to modify a JSON with values from another JSON in PowerShell


I'm trying to modify some appsettings.json inside a folder using values inside another json to unify the configuration of the files, but I/m not sure why it is not working

my appsettings have the following format

{
    //some comment
    "AppNameURI": "",
    "DB": {
        "ConnectionString": "mySQLStringConnection",
        "Provider": "SqlServer"
    },
    "Service01": {
        "BaseUrl": "http://myservice",
        "Service1": "wheater"
    }
}

my json with the values is like this

{
    "authorized": true,
    "description": "",
    "id": 6,
    "name": "Develop",
    "providerData": null,
    "type": "Vsts",
    "variables": {
        "DB.ConnectionString": {
            "isSecret": null,
            "value": "myConnectionString"
        },
        "Service01.BaseUrl": {
            "isSecret": null,
            "value": "https://mygroupofservices.com"
        },
        "Service01.Service1": {
            "isSecret": null,
            "value": "getWeather"
        }
    }
}

the idea is that when I execute a powershell script it replaces all the values if they are being used in some application to get something like this:

{
    "AppNameURI": "",
    "DB": {
        "ConnectionString": "myConnectionString",
        "Provider": "SqlServer"
    },
    "Service01": {
        "BaseUrl": "https://mygroupofservices.com",
        "Service1": "getWeather"
    }
}

this is my powerShell script

# Vars
$baseDir = "HIS\API" # the base path to my applications
$replacementFilePath = "Parameters-localhost.json" # the file with the values

# Read vars file
if (-Not (Test-Path $replacementFilePath)) {
    Write-Host "The vars file doesn't exist: $replacementFilePath" -ForegroundColor Red
    exit
}

$replacementData = Get-Content $replacementFilePath -Raw | ConvertFrom-Json

if (-Not $replacementData.variables) {
    Write-Host "The file doesn't have values." -ForegroundColor Red
    exit
}

# Make a dictionary
$replacements = @{}
foreach ($key in $replacementData.variables.PSObject.Properties.Name) {
    #$replacements[$key] = $replacementData.variables.PSObject.Properties[$key].Value
    
    $value = $replacementData.variables.PSObject.Properties["$key"].value.value
    $replacements[$key] = $value
    #Write-Host "'$key': $value"
}
        

# look for appsettings.json files recursively
Get-ChildItem -Path $baseDir -Recurse -Filter "appsettings.json" | ForEach-Object {
    $filePath = $_.FullName
    Write-Host "Processing file: $filePath" -ForegroundColor Cyan

    try {
        # read the current file
        Write-Host "Loading file ..." -ForegroundColor Cyan
        
        # Read and process line by line
        $jsontext = Get-Content $filePath | ForEach-Object {
            # delete special characters
            $line = $_

            # delete comments
            if ($line -match '^\s*//') {
                #Write-Host "Deleting comment: $line" -ForegroundColor Yellow
                $line = $line -replace '^\s*//.*$', ''
            }

            # Return the line
            $line
        } | Out-String
        #Write-Host $jsontext
        
        $jsonContent = $jsontext | ConvertFrom-Json -ErrorAction Stop
        
        # replaces
        Write-Host "looping keys" -ForegroundColor Cyan
        foreach ($key in $replacements.Keys){
            Write-Host " - - key: $key"
            $value = $replacements[$key]
            #Write-Host "'$key': '$value'"
            
            $pathParts = $key -split "\." # Splitting the key
            $property = $null
            foreach ($keyPart in $pathParts)
            {
                Write-Host $keyPart
                if($property -eq $null)
                {
                    $property = $jsonContent.PSObject.Properties[$keyPart]
                }
                else
                {
                    #$property = $property.PSObject.Properties[$keyPart]
                    $property = $property.$keyPart
                }
                Write-Host $property
            }
            if($property -ne $null) 
            {
                #Write-Host 'Property'
                #Write-Host $property
                Write-Host "setting '$key': '$value'"
                $property = $value
            }
        }

        # save changes
        $jsonContent | ConvertTo-Json -Depth 8 | Set-Content $filePath -Force
        Write-Host "Updating file: $filePath" -ForegroundColor Yellow
        
        exit
    } catch {
        Write-Host "Error processing $filePath" -ForegroundColor Red
        $errorMessage = $_.Exception.Message
        Write-Host ("{0}" -f $errorMessage) -ForegroundColor Red
    }
}

the Json file is modified by deleting comment lines, but the values are not updated


Solution

  • with Powershell 7.x

    $AppSettingHashtable = Get-Content $AppSettingJson -Raw | ConvertFrom-Json -Depth 100 -AsHashtable
    $MyValuesHashtable = Get-Content $MyValuesJson -Raw | ConvertFrom-Json -Depth 100 -AsHashtable
    
    
    foreach ($Key in $MyValuesHashtable.variables.Keys) {
        $Key1, $Key2 = $key -split '\.'
        $AppSettingHashtable[$Key1][$key2] = $MyValuesHashtable.variables[$Key].value
    }
    
    $AppSettingHashtable | ConvertTo-Json -Depth 100
    

    obviously make sure to match your paths as necessary