Конвертировать в 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

Чтобы дополнить полезный ответ Стивена кратким резюме и перекрестным обзором:

  • В PowerShell [Core] v7 + не требуется дополнительных усилий: добавление | ConvertFrom-Json | ConvertTo-Csvв код работает как есть.

  • В Windows PowerShell и PowerShell [Ядро] v6.x , вам нужно силы перечисления на ConvertFrom-Jsonвыходе «S для того , чтобы ConvertTo-Csvработать правильно, потому что, против обычного поведения PowerShell, в ConvertFrom-Jsonвыводит массив JSON в целом, как единый объект к трубопроводу .

    • Это необычное поведение вызвало изменение версии 7 + - см. Этот ответ для получения справочной информации.

    • Самый простой способ перечисления силы - то есть , чтобы отправить элементы AN / коллекции выхода-как-целое массива по одному к трубопроводу для использования (...), в группировке оператора .

# 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команде (неявной или иной) вместо того, чтобы передавать каждый объект по конвейеру по мере их создания. Вероятно, это следствие того, как написан командлет, и, возможно, он был необходим.

Ваш текущий код, вероятно, генерирует 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 ведет себя именно так. Я обновлю дополнительную информацию, когда найду более формальное объяснение.