1

I am querying the ResourceRecordSets in an AWS Route53 zone. I am trying to transform the name of the properties with select-object.

There are two records in the records sets. One has two items in the ResourceRecords the other has one item in ResourceRecords.

PS> (Get-R53ResourceRecordSet -HostedZoneId $zone.Id -MaxItem 1000).ResourceRecordSets

Name                    : simple.my-domain.com.
Type                    : A
SetIdentifier           : 
Weight                  : 0
Region                  : 
GeoLocation             : 
Failover                : 
MultiValueAnswer        : False
TTL                     : 300
ResourceRecords         : {Amazon.Route53.Model.ResourceRecord, Amazon.Route53.Model.ResourceRecord}
AliasTarget             : 
HealthCheckId           : 
TrafficPolicyInstanceId : 
CidrRoutingConfig       : 
GeoProximityLocation    : 

Name                    : weighted.my-domain.com.
Type                    : A
SetIdentifier           : my record id
Weight                  : 0
Region                  : 
GeoLocation             : 
Failover                : 
MultiValueAnswer        : False
TTL                     : 300
ResourceRecords         : {Amazon.Route53.Model.ResourceRecord}
AliasTarget             : 
HealthCheckId           : 
TrafficPolicyInstanceId : 
CidrRoutingConfig       : 
GeoProximityLocation    : 

Each Amazon.Route53.Model.ResourceRecord is an object with a single property named Value.

PS> (Get-R53ResourceRecordSet -HostedZoneId $zone.Id -MaxItem 1000).ResourceRecordSets[0].ResourceRecords | Get-Member

   TypeName: Amazon.Route53.Model.ResourceRecord

Name        MemberType Definition
----        ---------- ----------
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()
GetType     Method     type GetType()
ToString    Method     string ToString()
Value       Property   string Value {get;set;}

I want to rename ResourceRecords to resource_records and Value to value. To simplify and troubleshoot I am trying just to convert ResourceRecords to resource_records

PS> (Get-R53ResourceRecordSet -HostedZoneId $zone.Id -MaxItem 1000).ResourceRecordSets | Select-Object Name, Type, Weight, MultiValueAnswer, @{N='resource_records';E={$_.ResourceRecords}}

Name             : simple.my-domain.com.
Type             : A
Weight           : 0
MultiValueAnswer : False
resource_records : {Amazon.Route53.Model.ResourceRecord, Amazon.Route53.Model.ResourceRecord}

Name             : weighted.my-domain.com.
Type             : A
Weight           : 0
MultiValueAnswer : False
resource_records : Amazon.Route53.Model.ResourceRecord

But, it seems to convert the single item object array into an object. {Amazon.Route53.Model.ResourceRecord} has become Amazon.Route53.Model.ResourceRecord.

I have tried numerous ideas to try to prevent this from happening, and if it doesn't flat out fail it still always produces the same output.

For instance, I have tried casting it to an array:

PS> (Get-R53ResourceRecordSet -HostedZoneId $zone.Id -MaxItem 1000).ResourceRecordSets | Select-Object Name, Type, Weight, MultiValueAnswer, @{N='resource_records';E={@($_.ResourceRecords)}}

But, this doesn't make any difference.

Is there any way to prevent this from being converted into a non-array?

1 Answer 1

2

Given that you know $_.ResourceRecords to be an array, use the unary form of the array-construction operator , to wrap it in an an aux., transitory single-element array, so as to ultimately output it as-is.

Here's a simplified example:

@(
  [pscustomobject] @{ ResourceRecords = @(1) }
  [pscustomobject] @{ ResourceRecords = @(2, 3) }
) | 
  Select-Object @{ N='resource_records'; E={ , $_.ResourceRecords } }

The conceptually clearer, but more verbose and slower alternative is to use
Write-Output -NoEnumerate $_.ResourceRecords in lieu of , $_.ResourceRecords

This is necessary, because the output from a script block ({ ... }) assigned to the Expression (E) entry of a hashtable defining a calculated property exhibits pipeline logic:

  • That is, outputting an array causes it to be auto-enumerated, i.e. its elements are output, one by one, and if there happens to be just one element, that element is collected as-is; only two or more elements are captured in an array (of type [object[]], irrespective of the type of the source array).

  • The techniques above prevent this enumeration and ensure that the source array is preserved as-is as the value of the calculated property.

Sign up to request clarification or add additional context in comments.

3 Comments

This absolutely works. I'm still plugging away and expanding this to @{N='resource_records';E={, ($_.ResourceRecords | Select-Object @{N="value";E={$_.Value}})}} - that was one variation of attempts so far. Once I add the renaming of the value property I run in to the same problem.
Whew. Finally cracked it. Thanks for your help. @{N='resource_records';E={, @($_.ResourceRecords | foreach-object { @{"value" = $_.Value.Trim("`"")}})}}
Only just saw this now, @Appleoddity. I'm glad the answer helped and that you worked out the rest yourself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.