แปลงเป็น csv จาก json ใน powershell

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

เพื่อเสริมคำตอบที่เป็นประโยชน์ของ Stevenด้วยบทสรุปที่กระชับและมุมมองข้ามฉบับ:

  • ในPowerShell [Core] v7 +ไม่จำเป็นต้องใช้ความพยายามเพิ่มเติม: การต่อท้าย| ConvertFrom-Json | ConvertTo-Csvโค้ดของคุณจะทำงานได้ตามที่เป็นอยู่

  • ในWindows PowerShell และ PowerShell [หลัก] v6.xคุณจะต้องแจงนับแรงของConvertFrom-Jsonการส่งออกของเพื่อให้ConvertTo-Csvการทำงานได้อย่างถูกต้องเพราะกับพฤติกรรมปกติ PowerShell ของConvertFrom-Jsonเอาท์พุทอาร์เรย์ JSON เป็นทั้งเป็นวัตถุเดียวเพื่อท่อ .

    • เป็นความจริงที่ว่าพฤติกรรมนี้ผิดปกติที่แจ้งให้เกิดการเปลี่ยนแปลง v7 + - ดูคำตอบนี้สำหรับข้อมูลพื้นฐาน

    • วิธีที่ง่ายที่สุดในการบังคับใช้การแจงนับ - คือการส่งองค์ประกอบผลผลิต-as-a-ทั้งอาร์เรย์ / คอลเลกชันหนึ่งโดยหนึ่งไปยังท่อคือการใช้งาน(...)ที่ผู้ประกอบการจัดกลุ่ม

# 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คำสั่งเดียว(โดยนัยหรืออย่างอื่น) แทนที่จะสตรีมวัตถุแต่ละชิ้นไปตามท่อเมื่อสร้างขึ้น อาจเป็นผลมาจากวิธีการเขียน cmdlet และอาจจำเป็น

รหัสปัจจุบันของคุณมีแนวโน้มที่จะสร้าง csv เช่น:

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

นี่คือคุณสมบัติของอาร์เรย์ไม่ใช่วัตถุในอาร์เรย์ วิธีหนึ่งในการแก้ไขปัญหาเพียงแค่จอดข้อมูลไว้ในตัวแปร:

$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 โดยตรงเช่น$Json | ConvertFrom-Json | ConvertTo-Csv...คุณอาจมีปัญหาเดียวกัน

การทำซ้ำบนวัตถุ 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

อีกครั้งไม่แน่ใจ 100% ว่าทำไม ConvertFrom-Json จึงทำงานในลักษณะนี้ ฉันจะอัปเดตข้อมูลเพิ่มเติมเมื่อพบคำอธิบายที่เป็นทางการมากขึ้น