用Powershell查找并替换嵌套的JSON值

用Powershell查找并替换嵌套的JSON值,json,powershell,.net-core,azure-devops,Json,Powershell,.net Core,Azure Devops,我有一个appsettings.json文件,我想在VSTS发布管道PowerShell任务中使用PowerShell脚本对其进行转换。(顺便说一句,我正在为IIS部署NetStandard2API)。JSON的结构如下所示: { “Foo”:{ “BaseUrl”:http://foo.url.com", “UrlKey”:“12345” }, “酒吧”:{ “BaseUrl”:http://bar.url.com" }, “Blee”:{ “BaseUrl”:http://blee.url.

我有一个
appsettings.json
文件,我想在VSTS发布管道PowerShell任务中使用PowerShell脚本对其进行转换。(顺便说一句,我正在为IIS部署NetStandard2API)。JSON的结构如下所示:

{
“Foo”:{
“BaseUrl”:http://foo.url.com",
“UrlKey”:“12345”
},
“酒吧”:{
“BaseUrl”:http://bar.url.com"
},
“Blee”:{
“BaseUrl”:http://blee.url.com"
}
}
我想替换BaseUrl,如果它存在,则替换每个部分中的UrlKey值,即Foo、Bar和Blee。(Foo:BaseUrl、Foo:UrlKey、Bar:BaseUrl等)

我使用以下JSON结构来保存新值:

$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
{
“##{FooUrl}”:“$(FooUrl)”,
“##{FooUrlKey}”:“$(FooUrlKey)”,
“##{BarUrl}”:“$(BarUrl)”,
“#{BleeUrl}”:“$(BleeUrl)”
}
到目前为止,我有以下脚本:

#获取文件路径
$filePath=“C:\mywebsite\appsettings.json”
#从字符串解析JSON对象
$jsonString=“$(MyReplacementVariablesJson)”
$jsonObject=convertfromJSON$jsonString
#将JSON替换变量对象转换为哈希表
$hashTable=@{}
foreach($jsonObject.PSObject.Properties中的属性){
$hashTable[$property.Name]=$property.Value
}
#这是我需要帮助的地方
#执行变量替换
foreach($hashTable.Keys中的key){
$sourceFile=获取内容$filePath
$sourceFile-替换$key,$hashTable[$key]|设置内容$filePath
在“$filePath”中写入主机“将键“$key”替换为值“$hashTable[$key]”
}

为什么要将替换值定义为JSON字符串?那只会让你的生活更悲惨。如果要在脚本中定义值,请立即将其定义为哈希表:

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

$newKeys = @{
    'Foo' = '67890'
}
即使您想从文件中读取它们,也可以将该文件设置为包含这些哈希表的PowerShell脚本,并点源。或者至少将值定义为文本文件中的
key=value
行列表,这些行可以轻松转换为哈希表:

$newUrls = Get-Content 'new_urls.txt' | Out-String | ConvertFrom-StringData
$newKeys = Get-Content 'new_keys.txt' | Out-String | ConvertFrom-StringData
然后迭代输入JSON数据的顶级属性,并用新值替换嵌套属性:

$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
请注意,如果实际JSON数据的层次结构超过2级,则需要通过参数
-Depth
告诉
converttojson
,它应该转换多少级



旁注:需要通过
Out String
输出
Get Content
,因为
ConvertFrom Json
希望Json输入作为单个字符串,使用
Out String
可以使代码与所有PowerShell版本一起工作。如果您有PowerShell v3或更高版本,您可以通过将
获取内容|输出字符串
替换为
获取内容-原始

来简化代码。谢谢您,Ansgar提供了详细的回答,这对我帮助很大。最终,在没有机会迭代输入JSON数据的顶级属性之后,我决定使用以下代码:

$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

我希望这可以帮助其他人。

我得到“在该对象上找不到属性'BaseUrl'。请验证该属性存在并且可以设置。”如何检查以确保该名称具有BaseUrl属性?例如,Foo有BaseUrl,而Baz没有。对于类似的内容,您需要枚举
$json.$name
的属性。