我有一个
function
,它需要一个object
,其中有一堆properties
,最终它从该输入对象创建一个新对象。我将 field-mapping的
dictionary
传递给它,告诉函数输入对象的哪些 property
应该映射 并重命名 到新结果对象的属性名称。因此,例如输入对象可以有二十个属性,但我可能只对具有五个属性的新对象和这些属性的新名称感兴趣,这样我将拥有一个包含五个属性的映射。
我的功能有效,也非常欢迎您使其变得更好或更高效。
但我的主要问题是为什么结果中属性的order与我的字段映射字典的键顺序不同。
这是重新创建它的代码和数据:
function Convert-APIObjectToCustomObject {
param (
[Array]$dataFromAPI,
[Hashtable]$fieldMap
)
$resultData = @()
foreach ($item in $dataFromAPI) {
$newObject = New-Object -TypeName PSCustomObject
foreach ($key in $fieldMap.Keys) {
$matchedProperty = $item.PSObject.Properties | Where-Object { $_.Name.ToLower() -eq $fieldMap[$key].ToLower() }
if ($matchedProperty) {
$propertyValue = $matchedProperty.Value
} else {
Write-Warning "Property '$($fieldMap[$key])' not found on the input object. Setting default value."
$propertyValue = $null # or you can set it to '' for an empty string
}
$newObject | Add-Member -MemberType NoteProperty -Name $key -Value $propertyValue
}
$resultData += $newObject
}
return $resultData
}
# Example usage:
$dataFromAPI = @(
[PSCustomObject]@{ InstrumentId='1'; ServiceLayer='Service1'; MaturityDate=1; Gheimat='5' ; ExtraCol = '45' },
[PSCustomObject]@{ InstrumentId='2'; ServiceLayer='Service2'; MaturityDate=2; Gheimat='17'; ExtraCol = '1000'},
[PSCustomObject]@{ InstrumentId='3'; ServiceLayer='Service1'; MaturityDate=1; Gheimat='3' ; ExtraCol = 'Hi'},
[PSCustomObject]@{ InstrumentId='4'; ServiceLayer='Service1'; MaturityDate=1; Gheimat='7' ; ExtraCol = 'Hello' }
)
$fieldsMap = @{
"Id" = "InstrumentId"
"Service" = "ServiceLayer"
"Propertyx" = "MaturityDate"
"Price" = "Gheimat"
}
$resultData2 = Convert-APIObjectToCustomObject -dataFromAPI $dataFromAPI -fieldMap $fieldsMap
所以我希望结果中出现的属性的 order 与我在
"keys"
中定义的 fieldMap
的顺序相同。但目前情况并非如此。我怎样才能做到这一点?
您的代码的问题是变量
$fieldMap
是 Hashtable
而不是 OrderedDictionary
。下一个问题是参数 -fieldMap
键入为 Hashtable
而不是 IDictionary
或 OrderedDictionary
。
.PSObject.Properties
来反映循环中 $item
的属性。您还可以再次使用 OrderedDictionary
构造新对象,然后将其转换为 [pscustomobject]
类型加速器。这极大地提高了您的代码效率,与此技术相比,
Add-Member
非常慢。最后,您可以从函数中传输对象,无需+=
到数组。效率也很低,参见
script-authoring-considerations#array-addition
。
总结(使用与问题中相同的$dataFromAPI
来获取更短的代码):
function Convert-APIObjectToCustomObject {
param (
[Array] $dataFromAPI,
[System.Collections.IDictionary] $fieldMap
)
foreach ($item in $dataFromAPI) {
$newObject = [ordered]@{}
$reflectedProperties = $item.PSObject.Properties
foreach ($key in $fieldMap.Keys) {
$matchedProperty = $reflectedProperties[$fieldMap[$key]]
if ($matchedProperty) {
$propertyValue = $matchedProperty.Value
}
else {
Write-Warning "Property '$($fieldMap[$key])' not found on the input object. Setting default value."
$propertyValue = $null # or you can set it to '' for an empty string
}
$newObject[$key] = $propertyValue
}
[pscustomobject] $newObject
}
}
$dataFromAPI = @(
# same as before
)
$fieldsMap = [ordered]@{
'Id' = 'InstrumentId'
'Service' = 'ServiceLayer'
'Propertyx' = 'MaturityDate'
'Price' = 'Gheimat'
}
Convert-APIObjectToCustomObject -dataFromAPI $dataFromAPI -fieldMap $fieldsMap