Konwertuj na csv z json w programie PowerShell

Sep 23 2020

to jest mój csv:

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

Daje mi:

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

Chciałbym teraz odzyskać ten plik csv z mojego json, jednak łańcuchy | ConvertFrom-Json | ConvertTo-CSV nie działają, a jestem ciekaw, dlaczego nie?

Odpowiedzi

1 mklement0 Sep 25 2020 at 05:11

Aby uzupełnić pomocną odpowiedź Stevena zwięzłym podsumowaniem i perspektywą obejmującą różne wydania:

  • W PowerShell [Core] v7 + nie jest potrzebny żaden dodatkowy wysiłek: dołączanie | ConvertFrom-Json | ConvertTo-Csvdo kodu działa tak, jak jest.

  • W programie Windows PowerShell i PowerShell [Core] v6.x musisz wymusić wyliczenie danych ConvertFrom-Jsonwyjściowych, ConvertTo-Csvaby działało poprawnie, ponieważ w przeciwieństwie do zwykłego zachowania programu PowerShell ConvertFrom-Jsonwyprowadza tablicę JSON jako całość, jako pojedynczy obiekt do potoku .

    • Fakt, że to zachowanie jest niezwykłe , spowodował zmianę wersji 7 + - zobacz tę odpowiedź, aby uzyskać dodatkowe informacje.

    • Najprostszym sposobem na wyliczenie siły - czyli wysłać elementy wyjście-as-a-cały Array / odbioru za jeden po drugim do rurociągu jest do użytku (...), na operatora grupowania .

# 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

To daje:

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

Dane wyjściowe ConvertFrom-Jsonto pojedyncza tablica przekazywana w potoku jako taka. Jest to konsekwencja tego, jak ConvertFrom-Jsonpisze swoje wyjście. Prawdopodobnie zbiera wszystko i wyprowadza tablicę w jednym Write-Outputpoleceniu (niejawnym lub nie) zamiast przesyłać strumieniowo każdy obiekt w dół potoku podczas ich tworzenia. Prawdopodobnie jest to konsekwencja tego, jak napisane jest polecenie cmdlet i mogło być konieczne.

Twój obecny kod prawdopodobnie generuje plik CSV, taki jak:

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

To są właściwości tablicy, a nie zawarte w niej obiekty. Jednym ze sposobów obejścia tego problemu jest po prostu zaparkowanie danych w zmiennej:

$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

Uwaga: jeśli wyślesz $ Json bezpośrednio $Json | ConvertFrom-Json | ConvertTo-Csv..., możesz mieć ten sam problem.

Iteracja po obiektach Json również wydaje się działać:

$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

Dzięki @notjustme możesz to skrócić za pomocą (...):

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

Uwaga: poprawione zgodnie z odpowiedzią mklement0 .

Wszystkie te opcje zasadniczo polegają na umieszczeniu tablicy przed potokiem, aby ominąć wewnętrzne zachowanie ConvertFrom-Json

Ponownie nie jestem w 100% pewien, dlaczego ConvertFrom-Json zachowuje się w ten sposób. Zaktualizuję o dodatkowe informacje, gdy znajdę bardziej formalne wyjaśnienie.