dcvl
dcvl

Reputation: 595

Replace/rename object property name

I need to replace ip-netmask with fqdn if dns resolution is successful.

This script will be used to replace values in a config file.

If DNS is resolved, I need to change the property name of ip-netmask to fqdn and store the new dns value under it. The script resolves DNS and only updates ip-netmask if successful, and is also adding an fqdn property with the DNS value if successful.

Seems like I’m sort of there, but I am not able to rename ip-netmask to fqdn, or just delete the ip-netmask property without making my fqdn property null

From original json input

@'{
    "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"
        }
    ]
}

Here's my script

$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

And here's the output:

{
    "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"
        }
    ]
}

Upvotes: 3

Views: 17271

Answers (3)

SimonTi
SimonTi

Reputation: 21

I'm using :

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 )
    }
}

Upvotes: 1

Almighty
Almighty

Reputation: 178

There is actually a really simple way of doing this without the need of removing anything. I spent a lot of time troubleshooting my own issue so forgive me for not converting names into your context, but hope this helps. This is my first post to the community, so take it easy on me lol.


The starting properties of my PSCustomObject (same would apply to any object). The goal was to rename the property names and in my case retain a certain order.

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

Solution

$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}}

Now you can see that the PSCustomObject just gets stored into a new object with the custom renamed property fields.

$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

Upvotes: 1

Theo
Theo

Reputation: 61123

You shouldn't try to rename an existing property, but instead remove it and add the new NoteProperty to the object, like this:

$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

However, I believe you're using the wrong method for retrieving the fqdn from an IP address.. Shouldn't that be:

$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

Hope that helps


As per your comment, the order in which the properties are displayed is important to you.

To maintain that order, use

$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

Upvotes: 5

Related Questions