LoginSignup
3
7

More than 3 years have passed since last update.

ConvertFrom-Jsonの出力はPSCustomObject

Last updated at Posted at 2020-08-05

タイトル通り。
ハッシュテーブルだと思い込んでちょっと悩んだ。

JSONから変換したオブジェクトにAddできない?

JSONに要素を追加する際、文字列を直接切り張りしていたらキリストがお嘆きになろうから、オブジェクトに変換して操作しようと思った。
が、エラーになる。

JSONに要素を追加したい
$JSON = @'
{
  "alpha": "One",
  "beta" : "Two",
  "gamma": "Three",
  "delta": [ "Four", "Five" ]
}
'@

$Object = $JSON | ConvertFrom-Json

$Object.Add("nu","Six") #エラーになる
[System.Management.Automation.PSCustomObject] に 'Add' という
名前のメソッドが含まれないため、メソッドの呼び出しに失敗しました。

おや?エラーを見るとPSCustomObjectとある。
あれ?Hashtableじゃない…。

ConvertFrom-JsonはPSCustomObjectを出力する

何だこれと調べたところ、公式ドキュメントにしっかり書いてあった。
ConvertFrom-Json(公式ドキュメント)

ConvertFrom-Jsonコマンドレットは、JavaScript Object Notation(JSON)形式の文字列を、JSON文字列の各フィールドのプロパティを持つカスタムPSCustomObjectオブジェクトに変換します

Convert前後での変化
$Array = @{
  alpha = "One"
  beta = "Two"
  gamma = "Three"
  delta = @("Four","Five")
}

$Array.GetType()

# JSONにConvertして戻すとPSCustomObjectで出てくる
$Array_AfterConvert = $Array | ConvertTo-Json | ConvertFrom-Json

$Array_AfterConvert.GetType()
IsPublic IsSerial Name           BaseType
-------- -------- ----           --------
True     True     Hashtable      System.Object
True     False    PSCustomObject System.Object

仕様です。
思い込んでないで疑え、迷うより公式読めって話ですね。

これで終わりだと寂しいので当初の目的である要素追加や型変換などのことを以下に。

PSCustomObjectに要素を追加する

Add-Memberを使う。
Add-Member(公式ドキュメント)

Add-Memberで要素追加
$JSON =@'
{
  "alpha": "One",
  "beta" : "Two",
  "gamma": "Three",
  "delta": ["Four","Five"]
}
'@

$Object = $JSON | ConvertFrom-Json

Write-Host "Add前"
$Object | Format-List

$Object | Add-Member -NotePropertyName "nu" -NotePropertyValue "Six"

Write-Host "Add後"
$Object | Format-List

Write-Host "Get-Member"
$Object | Get-Member
Add前

alpha : One
beta  : Two
gamma : Three
delta : {Four, Five}

Add後

alpha : One
beta  : Two
gamma : Three
delta : {Four, Five}
nu    : Six

Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition                    
----        ----------   ----------                    
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()             
GetType     Method       type GetType()                
ToString    Method       string ToString()             
alpha       NoteProperty string alpha=One              
beta        NoteProperty string beta=Two               
delta       NoteProperty Object[] delta=System.Object[]
gamma       NoteProperty string gamma=Three            
nu          NoteProperty string nu=Six   

PSCustomObjectからHashtableに変換したい

コマンドレット一発変換とはいかない。
先にハッシュテーブルを作っておいて、PSCustomObjectから読み込んで代入するといいようだ。ジャグ配列の時は注意な!な話もあってまだ使ってない。

PSCustomObject について知りたかったことのすべて(MSのドキュメント)
stackoverflow:Create Hashtable from JSON

AsHashtableパラメータ指定して変換(PowerShell 7)

PowerShell 7 では、ConvertFrom-Json -AsHashtable とパラメータ指定するとハッシュテーブルに変換してくれる。7を使える環境なら悩まなくていい。

ConvertFrom-Json(公式ドキュメント)
[PowerShell 7] ConvertFrom-Json を使用して JSON データを読み込む

追記:JavaScriptSerializer.Deserializeメソッドで変換

JavaScriptSerializer.DeserializeメソッドでJSONをハッシュテーブルに変換できる。PowerShell 7でなくても使える。(ver5で確認)

PowerShell で JSON 変換をするときに発生するアレコレ
JavaScriptSerializer クラス
JavaScriptSerializer.Deserializeメソッド

3
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
7