PowerShellのjsonからcsvに変換する

Sep 23 2020

これは私のcsvです:

"name,data
Play,http://{gho}.domain.com/
BDomain,domain.com
Charts,2
Compress,0
CompressJ,0" | ConvertFrom-Csv | ConvertTo-Json

私に与える:

[
{
    "name":  "Play",
    "data":  "http://{gho}.domain.com/"
},
{
    "name":  "BDomain",
    "data":  "domain.com"
},
{
    "name":  "Charts",
    "data":  "2"
},
{
    "name":  "Compress",
    "data":  "0"
},
{
    "name":  "CompressJ",
    "data":  "0"
}
]

そのcsvをjsonから取得したいのですが、|のチェーン ConvertFrom-Json | ConvertTo-CSVが機能していません。なぜだろうか?

回答

1 mklement0 Sep 25 2020 at 05:11

スティーブンの有益な答えを簡潔な要約とクロスエディションの視点で補完するには:

  • ではPowerShellの[コア] V7 +、余分な手間は必要ありません:追加| ConvertFrom-Json | ConvertTo-Csvとして-であなたのコードの作品に。

  • で[コア]のv6.xのWindows PowerShellとPowerShellの、あなたがする必要が列挙強制のConvertFrom-Jsonためにはの出力ConvertTo-CsvのPowerShellの通常の行動に対して、あるため、正常に動作するようにConvertFrom-JsonJSON配列を出力し、単一のオブジェクトとして、全体としてパイプラインへ。

    • v7 +の変更を促したのは、この動作が異常であるという事実です。背景情報については、この回答を参照してください。

    • 列挙を強制する最も簡単な方法-つまり、配列全体としての出力/コレクションの要素を1つずつパイプラインに送信する(...)には、グループ化演算子を使用します。

# Works in all PowerShell versions, but in v7+ the (...) is no longer necessary.
(
"name,data
Play,http://{gho}.domain.com/
BDomain,domain.com
Charts,2
Compress,0
CompressJ,0" | ConvertFrom-Csv | ConvertTo-Json |
  ConvertFrom-Json
) | ConvertTo-Csv -NoTypeInformation

これにより、次のようになります。

"name","data"
"Play","http://{gho}.domain.com/"
"BDomain","domain.com"
"Charts","2"
"Compress","0"
"CompressJ","0"
2 Steven Sep 22 2020 at 23:59

の出力はConvertFrom-Json、パイプラインに渡される単一の配列です。これは、ConvertFrom-Json出力の書き込み方法の結果です。おそらくWrite-Output、作成時に各オブジェクトをパイプラインにストリーミングするのではなく、すべてを収集し、1つのコマンド(暗黙的またはその他)で配列を出力します。これはおそらく、コマンドレットの記述方法の結果であり、必要だった可能性があります。

現在のコードは、次のようなcsvを生成している可能性があります。

"Count","Length","LongLength","Rank","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized"
"5","5","5","1","System.Object[]","False","True","False"

これらは配列のプロパティであり、その中のオブジェクトではありません。それを回避する1つの方法は、データを変数にパークするだけです。

$Json = "name,data Play,http://{gho}.domain.com/ BDomain,domain.com Charts,2 Compress,0 CompressJ,0" | ConvertFrom-Csv | ConvertTo-Json # Now you can convert back to csv without issue: $Json = $Json | ConvertFrom-Json $Json | ConvertTo-Csv -NoTypeInformation

注:$Json | ConvertFrom-Json | ConvertTo-Csv...同じ問題が発生する可能性があるように、$ Jsonを直接送信した場合。

Jsonオブジェクトを反復処理することも機能するようです。

$Json = "name,data Play,http://{gho}.domain.com/ BDomain,domain.com Charts,2 Compress,0 CompressJ,0" | ConvertFrom-Csv | ConvertTo-Json $Json | 
ConvertFrom-Json |
ForEach-Object{ $_ } | 
ConvertTo-Csv -NoTypeInformation

@notjustmeのおかげで、次の(...)ように使用してこれを短縮できます。

($json | ConvertFrom-Json) | ConvertTo-Csv

注:mklement0の回答ごとに修正されました。

これらのオプションはすべて、基本的にアレイをパイプの前に配置して、の内部動作をバイパスします。 ConvertFrom-Json

繰り返しますが、ConvertFrom-Jsonがこのように動作する理由は100%わかりません。より正式な説明が見つかったら、追加情報で更新します。