Converter para csv de json em powershell
este é meu csv:
"name,data
Play,http://{gho}.domain.com/
BDomain,domain.com
Charts,2
Compress,0
CompressJ,0" | ConvertFrom-Csv | ConvertTo-Json
Dá-me:
[
{
"name": "Play",
"data": "http://{gho}.domain.com/"
},
{
"name": "BDomain",
"data": "domain.com"
},
{
"name": "Charts",
"data": "2"
},
{
"name": "Compress",
"data": "0"
},
{
"name": "CompressJ",
"data": "0"
}
]
Agora, gostaria de obter esse csv de volta do meu json, mas as cadeias de | ConvertFrom-Json | O ConvertTo-CSV não está funcionando e estou curioso para saber por que não?
Respostas
Para complementar a resposta útil de Steven com um resumo sucinto e uma perspectiva de várias edições:
No PowerShell [Core] v7 + , nenhum esforço extra é necessário: anexar
| ConvertFrom-Json | ConvertTo-Csvao seu código funciona como está.No Windows PowerShell e PowerShell [Core] v6.x , você precisa forçar a enumeração da
ConvertFrom-Jsonsaída deConvertTo-Csvpara funcionar corretamente, porque, contra o comportamento normal do PowerShell,ConvertFrom-Jsongera uma matriz JSON como um todo, como um único objeto para o pipeline .É o fato de que esse comportamento é incomum que levou à mudança na v7 + - consulte esta resposta para obter informações básicas.
A maneira mais simples de forçar a enumeração - ou seja, enviar elementos de uma coleção / array de saída como um todo, um por um, para o pipeline é usar
(...)o operador de agrupamento .
# 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
Isso produz:
"name","data"
"Play","http://{gho}.domain.com/"
"BDomain","domain.com"
"Charts","2"
"Compress","0"
"CompressJ","0"
A saída de ConvertFrom-Jsonuma única matriz sendo passada pelo pipeline como tal. Isso é uma consequência de como ConvertFrom-Jsonestá escrevendo sua saída. Provavelmente, ele está coletando tudo e gerando o array em um Write-Outputcomando (implícito ou não) em vez de fazer o streaming de cada objeto pelo pipeline à medida que são criados. É provavelmente uma consequência de como o cmdlet foi escrito e pode ter sido necessário.
Seu código atual provavelmente está gerando um csv como:
"Count","Length","LongLength","Rank","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized"
"5","5","5","1","System.Object[]","False","True","False"
Essas são as propriedades da matriz, não os objetos nela. Uma maneira de contornar isso é estacionar os dados em uma variável:
$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
Nota: se você enviar $ Json diretamente como
$Json | ConvertFrom-Json | ConvertTo-Csv...você pode ter o mesmo problema.
Iterar sobre os objetos Json também parece funcionar:
$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
Graças a @notjustme, você pode encurtar isso usando (...)como:
($json | ConvertFrom-Json) | ConvertTo-Csv
Nota: corrigido de acordo com a resposta de mklement0 .
Todas essas opções são essencialmente posicionar a matriz na frente do tubo para contornar o comportamento interno de ConvertFrom-Json
Mais uma vez, não tenho 100% de certeza por que ConvertFrom-Json se comporta dessa maneira. Atualizarei com informações adicionais quando encontrar uma explicação mais formal.