🐾

PowerShellのクラスにPSCustomObjectを変換する

2025/01/17に公開

PowerShellのクラスをJsonにするのはスゲー簡単

class Setting {
    [string]$Sample
}
$Conf = New-Object FolderMonitorConf -Property @{
    Sample = "aaa"
}
$Conf | ConvertTo-Json | Out-File -FilePath $Path

でもコレ、こんな風に普通に読み出すとPSCustomObjectになりやがるんだわ
事後のアクセス方法とか見かけ全然違和感がないんで最初全然気づかなかったんだけどさ

$psco = Get-Content -Path $Path | ConvertFrom-Json

本題

つーわけで、とりあえずこーしてくれるコトにした
例によってパフォーマンスは気にしない/気にするなら普通に.Netで書くでしょ
※変換元クラスのプロパティを扱うのでメンバ変数だけじゃ駄目です
 Add-Type -TypeDefinitionでC#のクラス定義を生成した場合は注意が必要

function ConvertFromPSCO {
    param (
        [Parameter(Mandatory = $true)] [System.Type]    $Type,
        [Parameter(Mandatory = $true)] [PSCustomObject] $Data
    )
    begin {}
    process {
        if ($null -eq $Data) {
            return $null
        }
        if ($Type.IsPrimitive) {
            return $Data
        } elseif ($Type.IsEnum) {
            return $Data
        } elseif (($Type.Name -eq "string") -or ($Type.Name -eq "datetime") -or ($Type.Name -eq "decimal")) {
            return $Data
        } elseif ($Type.IsArray) {
            $inst = @()
            foreach ($elm in $Data) {
                $inst += ConvertFromPSCO -Type $Type.GetElementType() -Data $elm
            }
            return $inst
        } elseif ($Type.IsClass -and -not $Type.IsValueType) {
            $inst = New-Object -TypeName $Type.FullName
            $Data.PSObject.Properties | ForEach-Object {
                $prop = $Type.GetProperty($_.Name)
                if ($null -ne $prop -and $prop.CanRead -and $prop.CanWrite) {
                    $inst.($_.Name) = ConvertFromPSCO -Type $Type.GetProperty($_.Name).PropertyType -Data $Data.($_.Name)
                }
            }
            return $inst
        } else {
            return $Data
        }
        return $null
    }
    end {}
}

こんな風に使う

$psco = Get-Content -Path $Path | ConvertFrom-Json
$Conf = ConvertFromPSCO ([Setting]) $psco

まぁ実はコレPowerShell7だと[System.Convert]::ChangeType($psco, ([Setting]))でいい
だからというかそれなりに動いてりゃ良いかな程度のデキになってる(ぉぃ

Discussion