Chuyển đổi sang csv từ json trong powershell

Sep 23 2020

đây là csv của tôi:

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

Đưa cho tôi:

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

Bây giờ tôi muốn lấy lại csv đó từ json của mình, tuy nhiên, chuỗi | ConvertFrom-Json | ConvertTo-CSV không hoạt động và tôi tò mò tại sao không?

Trả lời

1 mklement0 Sep 25 2020 at 05:11

Để bổ sung cho câu trả lời hữu ích của Steven bằng một bản tóm tắt ngắn gọn và quan điểm nhiều phiên bản:

  • Trong PowerShell [Core] v7 + , không cần thêm nỗ lực nào: việc bổ sung | ConvertFrom-Json | ConvertTo-Csvvào mã của bạn hoạt động như hiện tại.

  • Trong Windows PowerShell và PowerShell [lõi] v6.x , bạn cần phải có hiệu lực liệt kê của ConvertFrom-Json's đầu ra để cho ConvertTo-Csvcông việc một cách chính xác, bởi vì, đối với hành vi thông thường của PowerShell, ConvertFrom-Jsonkết quả đầu ra một mảng JSON như một toàn thể, như một đối tượng duy nhất để các đường ống dẫn .

    • Thực tế là hành vi này là bất thường đã thúc đẩy thay đổi v7 + - hãy xem câu trả lời này để biết thông tin cơ bản.

    • Cách đơn giản nhất để lực lượng điều tra - tức là để gửi các yếu tố sản lượng-như-một-toàn bộ mảng của bộ sưu tập / của từng người một để đường ống là để sử dụng (...), các nhà điều hành nhóm .

# 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

Điều này mang lại:

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

Đầu ra của ConvertFrom-Jsonlà một mảng đơn lẻ được chuyển xuống đường ống như vậy. Đây là hệ quả của cách ConvertFrom-Jsonviết đầu ra của nó. Nó có thể thu thập mọi thứ và xuất mảng trong một Write-Outputlệnh (ngầm định hoặc cách khác) thay vì truyền trực tuyến từng đối tượng xuống đường dẫn khi chúng được tạo. Đó có thể là hệ quả của cách viết lệnh ghép ngắn và có thể cần thiết.

Mã hiện tại của bạn có thể tạo ra một csv như:

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

Đây là các thuộc tính của mảng không phải là các đối tượng trong đó. Một cách để giải quyết vấn đề này chỉ cần đặt dữ liệu vào một biến:

$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

Lưu ý: nếu bạn gửi $ Json trực tiếp, $Json | ConvertFrom-Json | ConvertTo-Csv...bạn có thể gặp vấn đề tương tự.

Lặp lại các đối tượng Json dường như cũng hoạt động:

$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

Nhờ @notjustme, bạn có thể rút ngắn điều này bằng cách sử dụng (...)như:

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

Lưu ý: Đã sửa theo câu trả lời của mklement0 .

Tất cả các tùy chọn này về cơ bản là đặt mảng ở phía trước đường ống để bỏ qua hành vi bên trong của ConvertFrom-Json

Một lần nữa, không chắc chắn 100% tại sao ConvertFrom-Json hoạt động theo cách này. Tôi sẽ cập nhật thông tin bổ sung khi tôi tìm thấy lời giải thích chính thức hơn.