PowerShell:为 Select-Object 中的属性转换数据类型

PoweShell: Casting the data type for properties in Select-Object

我正在寻找一种在 PowerShell Select-Object.

期间转换数据类型的更有效方法(对于键入时间和性能)

目前,我将每个个体 属性 包装在一个表达式中以转换数据类型。我相信这不是正确的方法,只是感觉很脏...

我这样做的原因是我将数据发送到 REST API,它使用 JSON 模式应用严格验证。 $Data 中的数据不可靠。例如,属性 有时是 JSON 字符串 "12345",有时是意想不到的 JSON 整数 12345

REST API 然后 returns 出现 403 错误,因为它不希望该键为整数。

$Results = $Data | select ` 
    @{Name = 'Name'; expression = {[string]$_.DisplayName}}, 
    @{Name = 'Version'; expression = {[string]$_.DisplayVersion}},  
    @{Name = 'HelpLink'; expression = {[string]$_.HelpLink}}, 
    @{Name = 'InstallLocation'; expression = {[string]$_.InstallLocation}}, 
    @{Name = 'InstallSource'; expression = {[string]$_.InstallSource}}, 
    @{Name = 'Language'; expression = {[int]$_.Language}},  
    @{Name = 'DisplayIcon'; expression = {[string]$_.DisplayIcon}}, 
    @{Name = 'UninstallString'; expression = {[string]$_.UninstallString}}, 
    @{Name = 'WindowsInstaller'; expression = {[int]$_.WindowsInstaller}},
    @{Name = 'AppGUID'; expression = {[string]$_.APP_GUID}},  
    @{Name = 'URLInfoAbout'; expression = {[string]$_.URLInfoAbout}}, 
    @{Name = 'Vendor'; expression = {[string]$_.Publisher}}, 
    @{Name = 'InstallDate'; expression = {[int]$_.InstallDate}},
    @{Name = 'EstimatedSize'; expression = {[int]$_.EstimatedSize}},
    @{Name = 'VersionMajor'; expression = {[string]$_.VersionMajor}},
    @{Name = 'VersionMinor'; expression = {[string]$_.VersionMinor}},
    @{Name = 'SystemComponent'; expression = {[int]$_.SystemComponent}},
    @{Name = 'NoModify'; expression = {[string]$_.NoModify}},
    @{Name = 'NoRepair'; expression = {[string]$_.NoRepair}},
    @{Name = 'ModifyPath'; expression = {[string]$_.ModifyPath}},
    @{Name = 'BundleVersion'; expression = {[string]$_.BundleVersion}},
    @{Name = 'EngineVersion'; expression = {[string]$_.EngineVersion}}

我只会转换需要类型为 int 的属性。由于 PowerShell 是一种基于动态类型的语言,因此您可以执行以下操作:

$obj = [PSCustomObject] @{ Number = "123" }
$obj.Number.GetType() # Type is string
$obj.Number = [int] $obj.Number
$obj.Number.GetType() # Type is int

Output:
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
True     True     Int32                                    System.ValueType

您可以找到此示例 online。因此,您应该能够使用这种方法:

$Data.Language =  [int] $Data.Language

简而言之,您已经转换了需要属于 int 类型的属性。

更新 1

如果您的对象具有 "flat" 层次结构,您可以尝试以下操作:

$obj = [PSCustomObject]@{
    IntNr = "123"
    DecNr = "4,56"
    Str   = "abc"
}

$result = $obj.PSObject.Properties | ForEach-Object {
    [int] $parsedInt = 0
    [decimal] $parsedDec = 0.0
    if ([int]::TryParse($_.Value, [ref]$parsedInt)) {
        $_.Value = $parsedInt
    }
    elseif ([decimal]::TryParse($_.Value, [ref]$parsedDec)) {
        $_.Value = $parsedDec
    }
    $_
}

$result

转储时输出$result

 Value           : 123
 MemberType      : NoteProperty
 IsSettable      : True
 IsGettable      : True
 TypeNameOfValue : System.Int32
 Name            : IntNr
 IsInstance      : True

 Value           : 456
 MemberType      : NoteProperty
 IsSettable      : True
 IsGettable      : True
 TypeNameOfValue : System.Decimal
 Name            : DecNr
 IsInstance      : True

 Value           : abc
 MemberType      : NoteProperty
 IsSettable      : True
 IsGettable      : True
 TypeNameOfValue : System.String
 Name            : Str
 IsInstance      : True

此示例可在线获得link