问题
this is my csv:
"name,data
Play,http://{gho}.domain.com/
BDomain,domain.com
Charts,2
Compress,0
CompressJ,0" | ConvertFrom-Csv | ConvertTo-Json
Gives 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"
}
]
I would now like to get that csv back from my json, however the chains of | ConvertFrom-Json | ConvertTo-CSV are not working, and I am curious why not?
回答1:
To complement Steven's helpful answer with a succinct summary and a cross-edition perspective:
In PowerShell [Core] v7+, no extra effort is needed: appending
| ConvertFrom-Json | ConvertTo-Csv
to your code works as-is.In Windows PowerShell and PowerShell [Core] v6.x, you need to force enumeration of
ConvertFrom-Json
's output in order forConvertTo-Csv
to work correctly, because, against PowerShell's usual behavior,ConvertFrom-Json
outputs a JSON array as a whole, as a single object to the pipeline.It is the fact that this behavior is unusual that prompted the v7+ change - see this answer for background information.
The simplest way to force enumeration - i.e. to send an output-as-a-whole array's / collection's elements one by one to the pipeline is to use
(...)
, the grouping operator.
# 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
This yields:
"name","data"
"Play","http://{gho}.domain.com/"
"BDomain","domain.com"
"Charts","2"
"Compress","0"
"CompressJ","0"
回答2:
The output of ConvertFrom-Json
is single array being passed down the pipeline as such. This is a consequence of how ConvertFrom-Json
is writing it's output. It's probably collecting everything and outputting the array in one Write-Output
command (implicit or otherwise) instead of streaming each object down the pipeline as they are created. It's probably a consequence of how the cmdlet is written and may have been necessary.
Your current code is likely generating a csv like:
"Count","Length","LongLength","Rank","SyncRoot","IsReadOnly","IsFixedSize","IsSynchronized"
"5","5","5","1","System.Object[]","False","True","False"
These are the properties of the array not the objects in it. One way to get around it just park the data in a variable:
$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
Note: if you send $Json directly like
$Json | ConvertFrom-Json | ConvertTo-Csv...
you may have the same issue.
Iterating over the Json objects also seems to work:
$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
Thanks to @notjustme , you can shorten this using (...)
like:
($json | ConvertFrom-Json) | ConvertTo-Csv
Note: Corrected per mklement0's answer.
All of these options are essentially placing the array in-front of the pipe to bypass the internal behavior of ConvertFrom-Json
Again not 100% sure why ConvertFrom-Json behaves this way. I'll update with additional information when I find a more formal explanation.
来源:https://stackoverflow.com/questions/64014087/convert-to-csv-from-json-in-powershell