替换/重命名对象属性名称

3
我需要在 DNS 解析成功后将 "ip-netmask" 替换为 "fqdn"。
此脚本用于替换配置文件中的值。
如果成功解析了 DNS,我需要将 "ip-netmask" 的属性名称更改为 "fqdn",并在其下存储新的 DNS 值。该脚本会解析 DNS,并仅在成功时更新 ip-netmask 属性,并添加一个 fqdn 属性,其中包含 DNS 值。
看起来我已经接近目标了,但是我无法将 ip-netmask 重命名为 fqdn,也无法删除 ip-netmask 属性而不使我的 fqdn 属性为空。
从原始 JSON 输入开始。

@'
{
    "entry":[
        {
            "@name":"31.170.162.203",
            "ip-netmask":"31.170.162.203",
            "description":"test1"
        },
        {
            "@name":"37.193.217.222",
            "ip-netmask":"37.193.217.222",
            "description":"test2"
        },
        {
            "@name":"46.17.63.169",
            "ip-netmask":"46.17.63.169",
            "description":"test3"
        }
    ]
}


$a = Get-Content 'C:\Users\e\Desktop\puttytest1.json' | ConvertFrom-Json



$a.entry | ForEach-Object {

    if ($namehost = (Resolve-DnsName $_.'ip-netmask').namehost) {

        $_.'ip-netmask' = $namehost

        $_ | Add-Member -MemberType AliasProperty -Name fqdn -Value ip-netmask

        }
    }

$newjson = $a | ConvertTo-Json

$newjson

输出


{

    "entry":  [

                  {

                      "@name":  "31.170.165.68",

                      "ip-netmask":  "31.170.165.68",

                      "description":  "Test1"

                  },

                  {

                      "@name":  "31.170.162.203",

                      "ip-netmask":  "31.170.162.203",

                      "description":  "test2"

                  },

                  {

                      "@name":  "37.193.217.222",

                      "ip-netmask":  "l37-193-217-222.novotelecom.ru",

                      "description":  "test3",

                      "fqdn":  "l37-193-217-222.novotelecom.ru"

                  }

]

}

3个回答

5
你不应该试图重命名现有属性,而是应该删除它并向对象添加新的NoteProperty,像这样:
$newjson = $a.entry | ForEach-Object {
    if ($namehost = (Resolve-DnsName $_.'ip-netmask').namehost) {
        # remove the 'ip-netmask' property
        $_.PSObject.Properties.Remove('ip-netmask')
        # add a new NoteProperty 'fqdn'
        $_ | Add-Member -MemberType NoteProperty -Name 'fqdn' -Value $namehost
    }
} | ConvertTo-Json

然而,我认为您正在使用错误的方法从IP地址中检索fqdn。该方法不应该是:

$newjson = $a.entry | ForEach-Object {
    if ($namehost = [System.Net.Dns]::GetHostByAddress($($_.'ip-netmask')).HostName) {
        # remove the 'ip-netmask' property
        $_.PSObject.Properties.Remove('ip-netmask')
        # add a new NoteProperty 'fqdn'
        $_ | Add-Member -MemberType NoteProperty -Name 'fqdn' -Value $namehost
    }
} | ConvertTo-Json

希望能帮到你。
根据你的评论,你关心属性显示的顺序。
为了保持顺序,请使用
$newjson = $a.entry | ForEach-Object {
    if ($namehost = (Resolve-DnsName $_.'ip-netmask').namehost) {
        # output a new object with properties ordered like you want them to be
        $_ | Select-Object '@name', @{Name = 'fqdn'; Expression = {$namehost}}, 'description'
    }
    else { 
        # output the object unchanged
        $_ 
    }
} | ConvertTo-Json

第一个几乎是我想要的。我尝试过计算属性和一堆其他东西,但从未遇到过noteproperty。现在最后一件事……你知道如何将fqdn放在JSON结构中的ip-netmask字段所在位置吗?这是一个配置文件,所以顺序需要保持不变。这里的输出将fqdn放在描述之后的末尾。 - dcvl
我已经尝试在转换为JSON管道中选择对象并按顺序列出属性,但它没有起作用。 - dcvl
@dcvl 我已经编辑了我的答案,并添加了代码以保持属性顺序。 - Theo
太好了,谢谢!我自己无法让计算属性起作用。 - dcvl

1

我正在使用:

function Rename-Properties(){
    [CmdletBinding()]
    Param([Parameter(ValueFromPipeline=$true,Mandatory=$true,Position=0)][Object]$inputObject
        , [Parameter(ValueFromPipeline=$false,Mandatory=$false)][Object]$NewNames
        , [Parameter(ValueFromPipeline=$false,Mandatory=$false)][switch]$Keep=$false
    ) 
    # Parameter NewNames: can take (a mapping) HashTable{Key(NewName)=Value(Name)] 
    #   or object collection with properties Name,NewName 
    #      e.g. $myInputObject.PSObject.properties | Where-Object {$_.Name -like '*'} | Select-Object Name,@{N='NewName';E={"Prefixed_$($_.Name"}}
    if($NewNames -is [HashTable]) {  $NewNames = $NewNames.GetEnumerator() | Select-Object @{N='Name';E={$_.Value}},@{N='NewName';E={$_.Key}} }
    # ensure NewName exists and is unique
    $NewNames = ( $NewNames | Where-Object {$_.NewName.length -gt 0} | Group-Object -Property NewName | ForEach-Object{$_.Group[0]} )
    $props = @('*')
    ForEach($prp in $NewNames) {
        $props += @{N="$($prp.NewName)";E=([Scriptblock]::Create("`$_.$($prp.Name)"))}
    }
    if($Keep) {
        return  ($inputObject | Select-Object -Property $props )
    } else {
        return  ($inputObject | Select-Object -Property $props -ExcludeProperty $NewNames.Name )
    }
}

1

实际上有一种非常简单的方法可以做到这一点,无需删除任何内容。我花了很多时间来解决自己的问题,所以原谅我没有将名称转换为您的上下文,但希望这可以帮助到您。这是我第一次向社区发布帖子,所以请对我温柔一点。


我的PSCustomObject的起始属性(同样适用于任何对象)。目标是重命名属性名称,在我的情况下保留特定顺序。

$roleMappingsCSV | Get-Member -MemberType Properties | Select-Object Name, MemberType
Name             MemberType
----             ----------
Identifiers    NoteProperty
IdentifierType NoteProperty
InlinePolicy   NoteProperty
ManagedPolicy  NoteProperty
Members        NoteProperty
Role           NoteProperty 

解决方案

$roleMappingsCSV_Proper = $roleMappingsCSV | Select-Object @{N='IAM_Role'; E={$_.Role}},`
@{N='Basis_Type'; E={$_.IdentifierType}},`
@{N='Basis_for_Access'; E={$_.Identifiers}},`
@{N='Members'; E={$_.Members}},`
@{N='Managed_Policy'; E={$_.ManagedPolicy}},`
@{N='InlinePolicy'; E={$_.InlinePolicy}}

现在,您可以看到PSCustomObject只是被存储到一个新对象中,并带有自定义重命名的属性字段。
$roleMappingsCSV_Proper | Get-Member -MemberType Properties | Select-Object Name, MemberType
Name               MemberType
----               ----------
Basis_for_Access NoteProperty
Basis_Type       NoteProperty
IAM_Role         NoteProperty
InlinePolicy     NoteProperty
Managed_Policy   NoteProperty
Members          NoteProperty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接