Konversikan ke csv dari json di PowerShell

Sep 23 2020

ini csv saya:

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

Memberi saya:

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

Sekarang saya ingin mendapatkan csv itu kembali dari json saya, namun rantai | ConvertFrom-Json | ConvertTo-CSV tidak berfungsi, dan saya ingin tahu mengapa tidak?

Jawaban

1 mklement0 Sep 25 2020 at 05:11

Untuk melengkapi jawaban Steven yang bermanfaat dengan ringkasan singkat dan perspektif lintas edisi:

  • Di PowerShell [Core] v7 + , tidak diperlukan upaya ekstra: menambahkan | ConvertFrom-Json | ConvertTo-Csvkode Anda berfungsi sebagaimana adanya.

  • Di Windows PowerShell dan PowerShell [Inti] v6.x , Anda perlu kekuatan pencacahan dari ConvertFrom-Jsonkeluaran 's agar ConvertTo-Csvbekerja dengan benar, karena, terhadap perilaku biasa PowerShell ini, ConvertFrom-Jsonoutput array JSON secara keseluruhan, sebagai objek tunggal untuk pipa .

    • Fakta bahwa perilaku ini tidak biasa yang mendorong perubahan v7 + - lihat jawaban ini untuk informasi latar belakang.

    • Cara termudah untuk memaksa enumerasi - yaitu mengirim elemen array / collection output-as-a-whole satu per satu ke pipeline adalah dengan menggunakan (...), operator pengelompokan .

# 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

Ini menghasilkan:

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

Output dari ConvertFrom-Jsonlarik tunggal yang diteruskan ke pipa seperti itu. Ini adalah konsekuensi dari bagaimana ConvertFrom-Jsonmenulis outputnya. Ini mungkin mengumpulkan semuanya dan mengeluarkan array dalam satu Write-Outputperintah (implisit atau sebaliknya) alih-alih mengalirkan setiap objek ke dalam pipa saat dibuat. Ini mungkin konsekuensi dari bagaimana cmdlet ditulis dan mungkin diperlukan.

Kode Anda saat ini kemungkinan besar menghasilkan csv seperti:

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

Ini adalah properti dari array, bukan objek di dalamnya. Salah satu cara untuk menyiasatinya cukup dengan memarkir data dalam variabel:

$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

Catatan: jika Anda mengirim $ Json secara langsung seperti $Json | ConvertFrom-Json | ConvertTo-Csv...Anda mungkin mengalami masalah yang sama.

Iterasi di atas objek Json juga tampaknya berhasil:

$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

Berkat @notjustme, Anda dapat mempersingkat ini menggunakan (...)seperti:

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

Catatan: Dikoreksi sesuai jawaban mklement0 .

Semua opsi ini pada dasarnya menempatkan larik di depan pipa untuk melewati perilaku internal ConvertFrom-Json

Sekali lagi tidak 100% yakin mengapa ConvertFrom-Json berperilaku seperti ini. Saya akan memperbarui dengan informasi tambahan ketika saya menemukan penjelasan yang lebih formal.