如何在Powershell中替换JSON文件中的属性

时间:2018-10-11 19:43:11

标签: json powershell

我在用powershell读取JSON文件,替换值并写回该文件或文件时遇到了困难。

给出以下内容:

[Object]$QuickJson = @'
{
    "swagger": "1.0",
    "info": {
        "version": "0.0.1",
        "title": "this is a title",
        "description": "this is a description"
    },
    "basePath": "/test",   
    "paths" : {
        "/GetSomething": {
            "get": {
                "name" : "test01"
            }
        },
        "/GetSomethingElse" : {
            "get": {
                "name" : "test02"
            }
        },
        "/GetAnotherThing": {
            "get": {
                "name" : "test03"
            }
        }
    }
}
'@

我在这里感兴趣的是用其他东西替换“ paths”对象中的值。我读取了文件,但是可以通过尝试的操作访问该对象:

[object]$MyPSJson = ConvertFrom-Json -InputObject $QuickJson

foreach($info in $MyPSJson.paths.PSObject.Properties)
{
    $path = $info.Name
    Write-Host "path: $path"
    $info.Name = "$path?code=fsfsfsfsfsfdfds"

    Write-Host $info.Name 
}

我不知道这些“路径”将是什么,我需要采用现有值并向其附加代码值,因此我需要能够遍历所有路径并进行此替换。当我尝试上面的时候,我得到一个错误:

  

路径:/ GetSomething   -'名称'是ReadOnly属性。在C:\ scripts \ test.ps1:44 char:5   + $ info.Name =“ $ path?code = fsfsfsfsfsfdfds”   + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       + CategoryInfo:InvalidOperation:(:) [],RuntimeException       + FullyQualifiedErrorId:PropertyAssignmentException

我尝试了几种不同的方法,但仍未提出好的或可行的解决方案。任何帮助或指向正确的方向,我们将不胜感激。

3 个答案:

答案 0 :(得分:2)

您可以执行与现在非常相似的操作,只是无需更改记录初始属性的现有属性,而是添加具有所需修改的新属性,然后将$MyPSJson.paths设置为自身(不包括旧属性) ,所以所有这些都是新属性。

#Find initial paths
$Paths=$MyPSJson.paths.psobject.Properties.Name

#Add new paths with the modification to the name, and set the value to the same as the old path
$Paths|%{Add-Member -InputObject $MyPSJson.paths -NotePropertyName "$_`?code=fsfsfsfsfsfdfds" -NotePropertyValue $MyPSJson.paths.$_}

#Set the paths object to itself, excluding the original paths
$MyPSJson.paths = $MyPSJson.paths|Select * -ExcludeProperty $Paths

答案 1 :(得分:1)

尝试以下(PSv3 +):

$MyPSJson.paths = $MyPSJson.paths.psobject.properties |
  ForEach-Object { $renamedProps = [ordered] @{} } { 
    $renamedProps[$_.Name + '?foo=bar&baz=bam'] = $_.Value
  } { [pscustomobject] $renamedProps }

从技术上讲,此使用修改后的属性名称重新创建.paths对象。

通过枚举原始属性,将它们的修改后名称下的值添加到有序哈希表中来完成,该哈希表在管道完成后会转换为自定义对象([pscustomobject])。


关于您尝试过的事情

给定对象的属性不能重命名-只能更改其属性的

因此,必须使用所需的新属性名称和与原始属性相同的值创建一个 new 对象。

顺便说一句:[object]强制转换在PowerShell中是没有意义的-它是有效的禁止操作。
相比之下,[pscustomobject]强制转换可用于从[有序]哈希表中创建[pscustomobject]实例
,这是上面使用的技术;从其他类型进行的投射又是虚拟的无操作。

答案 2 :(得分:0)

除了对我有用的公认答案外,我还发现了最初建议的另一种使用哈希表的方法:

function Convert-JsonFileToHashTable([string]$file) {
    $text = [IO.File]::ReadAllText($file)
    $parser = New-Object Web.Script.Serialization.JavaScriptSerializer
    $parser.MaxJsonLength = $text.length
    $hashtable = $parser.Deserialize($text, @{}.GetType())

    return $hashtable
}

$hashtable = Convert-JsonFileToHashTable (Resolve-Path -Path $DefinitionFile)

$keys = New-Object System.Collections.ArrayList($null)
$keys.AddRange($hashtable["paths"].Keys)
foreach ($key in $keys) 
{
    $newPath = $key + "?code=$Code"
    $hashtable["paths"].$newPath = $hashtable["paths"].$key
    $hashtable["paths"].Remove($key) | Out-Null
}

$json = $hashtable | ConvertTo-Json -Depth 20
Write-Output $json | Out-File $newFile -Encoding utf8