3 votes

Rechercher et remplacer des valeurs JSON imbriquées avec Powershell

J'ai un appsettings.json que je voudrais transformer avec un script PowerShell dans une tâche PowerShell du pipeline de sortie de VSTS. (BTW je déploie un netstandard 2 Api à IIS). Le JSON est structuré comme suit :

{
    "Foo": {
        "BaseUrl": "http://foo.url.com",
        "UrlKey": "12345"
    },
    "Bar": {
        "BaseUrl": "http://bar.url.com"
    },
    "Blee": {
        "BaseUrl": "http://blee.url.com"
    }
}

Je veux remplacer BaseUrl et, si elle existe, les valeurs UrlKey de chaque section qui sont Foo, Bar et Blee. (Foo:BaseUrl, Foo:UrlKey, Bar:BaseUrl, etc.)

J'utilise la structure JSON suivante pour contenir les nouvelles valeurs :

{ 
    "##{FooUrl}":"$(FooUrl)", 
    "##{FooUrlKey}":"$(FooUrlKey)",
    "##{BarUrl}":"$(BarUrl)",
    "##{BleeUrl}":"$(BleeUrl)"
}

Jusqu'à présent, j'ai le script suivant :

# Get file path
$filePath = "C:\mywebsite\appsettings.json"

# Parse JSON object from string
$jsonString = "$(MyReplacementVariablesJson)"
$jsonObject = ConvertFrom-Json $jsonString

# Convert JSON replacement variables object to HashTable
$hashTable = @{}
foreach ($property in $jsonObject.PSObject.Properties) {
    $hashTable[$property.Name] = $property.Value
}

# Here's where I need some help

# Perform variable replacements
foreach ($key in $hashTable.Keys) {
    $sourceFile = Get-Content $filePath
    $sourceFile -replace $key, $hashTable[$key] | Set-Content $filePath
    Write-Host 'Replaced key' $key 'with value' $hashTable[$key] 'in' $filePath
}

3voto

Ansgar Wiechers Points 38466

Pourquoi définissez-vous vos valeurs de remplacement comme une chaîne JSON ? Cela va juste rendre votre vie plus misérable. Si vous définissez les valeurs dans votre script de toute façon, définissez-les tout de suite comme des hashtables :

$newUrls = @{
    'Foo'  = 'http://newfoo.example.com'
    'Bar'  = 'http://newbaz.example.com'
    'Blee' = 'http://newblee.example.com'
}

$newKeys = @{
    'Foo' = '67890'
}

Même si vous vouliez les lire depuis un fichier, vous pourriez faire de ce fichier un script PowerShell contenant ces hashtables et le dot-source. Ou au moins définir les valeurs comme des listes de key=value des lignes dans des fichiers texte, qui peuvent facilement être transformées en hashtables :

$newUrls = Get-Content 'new_urls.txt' | Out-String | ConvertFrom-StringData
$newKeys = Get-Content 'new_keys.txt' | Out-String | ConvertFrom-StringData

Ensuite, il faut itérer sur les propriétés de haut niveau de vos données JSON d'entrée et remplacer les propriétés imbriquées par les nouvelles valeurs :

$json = Get-Content $filePath | Out-String | ConvertFrom-Json
foreach ($name in $json.PSObject.Properties) {
    $json.$name.BaseUrl = $newUrls[$name]
    if ($newKeys.ContainsKey($name)) {
        $json.$name.UrlKey = $newKeys[$name]
    }
}
$json | ConvertTo-Json | Set-Content $filePath

Notez que si vos données JSON actuelles ont plus de 2 niveaux de hiérarchie, vous devrez indiquer à ConvertTo-Json via le paramètre -Depth combien de niveaux il est censé convertir.


Note complémentaire : la tuyauterie du Get-Content sortie par Out-String est nécessaire car ConvertFrom-Json s'attend à ce que l'entrée JSON soit une chaîne unique, et l'utilisation de l'option Out-String permet au code de fonctionner avec toutes les versions de PowerShell. Si vous avez PowerShell v3 ou une version plus récente, vous pouvez simplifier un peu le code en remplaçant Get-Content | Out-String avec Get-Content -Raw .

1voto

TrevorBrooks Points 1322

Merci, Ansgar, pour votre réponse détaillée, qui m'a beaucoup aidé. En fin de compte, après n'avoir eu aucune chance d'itérer sur les propriétés de haut niveau de mes données JSON d'entrée, j'ai opté pour le code suivant :

$json = (Get-Content -Path $filePath) | ConvertFrom-Json

    $json.Foo.BaseUrl = $newUrls["Foo"]
    $json.Bar.BaseUrl = $newUrls["Bar"]
    $json.Blee.BaseUrl = $newUrls["Blee"]

    $json.Foo.Key = $newKeys["Foo"]

$json | ConvertTo-Json | Set-Content $filePath

J'espère que cela pourra aider quelqu'un d'autre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X