在 powershell 中从 json 转换为 csv

Convert to csv from json in powershell

这是我的 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"
}
]

我现在想从我的 json 取回那个 csv,但是 | 的链ConvertFrom-Json | ConvertTo-CSV 不工作,我很好奇为什么不工作?

ConvertFrom-Json 的输出是单个数组被传递到管道中。这是 ConvertFrom-Json 如何编写其输出的结果。它可能会收集所有内容并在一个 Write-Output 命令(隐式或其他方式)中输出数组,而不是在创建对象时将每个对象沿管道流式传输。这可能是 cmdlet 编写方式的结果,可能是必要的。

您当前的代码可能生成如下 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

Note: if you send $Json directly like $Json | ConvertFrom-Json | ConvertTo-Csv... you may have the same issue.

迭代 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

Note: Corrected per .

所有这些选项本质上都是放置管道的数组 in-front 以绕过 ConvertFrom-Json

的内部行为

同样不能 100% 确定为什么 ConvertFrom-Json 会这样。当我找到更正式的解释时,我会更新更多信息。

用简洁的总结和 cross-edition 的视角来补充

  • PowerShell [Core] v7+ 中,不需要额外的努力:将 | ConvertFrom-Json | ConvertTo-Csv 附加到您的代码中 as-is。

  • WindowsPowerShell和PowerShell[Core]v6.x中,需要强制枚举[= ConvertFrom-Json 的输出的 47=] 以便 ConvertTo-Csv 正常工作,因为,与 PowerShell 的通常行为相反,ConvertFrom-Json 输出一个 JSON 数组 as一个整体,作为单个对象到管道。

    • 正是这种行为 不寻常 促使 v7+ 更改的事实 - 请参阅 了解背景信息。

    • 强制枚举的最简单方法——即将output-as-a-whole数组/集合的元素一个一个发送到管道是使用(...), 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

这产生:

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