Search code examples
powershellobjectrename

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

Solution

  • 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