使用PowerShell将JSON转换为CSV

13

我有一个样本JSON格式的这里,如果我使用类似https://konklone.io/json/这样的工具,则可以成功转换。

我已尝试在PowerShell中使用以下代码:

(Get-Content -Path $pathToJsonFile | ConvertFrom-Json) 
| ConvertTo-Csv -NoTypeInformation 
| Set-Content $pathToOutputFile

但是我得到的唯一结果就是这个:

{"totalCount":19,"resultCount":19,"hasMore":false,"results":

我该如何在PowerShell中正确转换这个?

4个回答

29

仅通过查看 (Get-Content -Path $pathToJsonFile) | ConvertFrom-Json,似乎其余的 JSON 都进入了一个名为 results 的属性,因此我们可以通过执行以下操作来获得您想要的结果:

((Get-Content -Path $pathToJsonFile) | ConvertFrom-Json).results |
    ConvertTo-Csv -NoTypeInformation |
    Set-Content $pathToOutputFile

你可以使用Export-CSV在一步中完成ConvertTo-CsvSet-Content的操作:

((Get-Content -Path $pathToJsonFile) | ConvertFrom-Json).results |
    Export-CSV $pathToOutputFile -NoTypeInformation

1
由于某种原因,在我的端上,源JSON文件中包含的数组被转换为结果的“SyncRoot”属性。所以我只需要用.SyncRoot替换.results即可。 - Dany Gauthier
1
@DanyGauthier,那是因为.results是JSON对象的名称。我猜你有一个名字叫做“SyncRoot”。我有一个名字叫做“Weights”。这让我困扰了一段时间,但是一旦我弄清楚了,它就起作用了 :) - Roman
8
因为我的JSON文件格式化过于复杂,所以我必须去掉“.results”并添加“-Raw”参数:((Get-Content -Path $pathToJsonFile -Raw) | ConvertFrom-Json) | Export-CSV $pathToOutputFile -NoTypeInformation。如果版本有影响,那是PowerShell 4版本。 - Piemol
点赞,我也不得不从这个一行代码中剥离出.results - MDMoore313
不需要在我的脚本中使用.results,只需返回我和它。 - ChumKui

9

您需要使用Select-Object命令和-expand参数,选择CSV中的results属性:

Get-Content -Path $pathToJsonFile  | 
    ConvertFrom-Json | 
    Select-Object -expand results | 
    ConvertTo-Csv -NoTypeInformation |
    Set-Content $pathToOutputFile

6

我从一个REST web api获取我的JSON数据,发现以下代码有效:

Invoke-WebRequest -method GET -uri $RemoteHost -Headers $headers 
 | ConvertFrom-Json 
 | Select-Object -ExpandProperty  <Name of object in json>
 | ConvertTo-Csv -NoTypeInformation 
 | Set-Content $pathToOutputFile

I end up with a perfectly formatted csv file

1
尝试使用Mark Wrang的答案对我无效。虽然Piemol在2019年1月30日的评论解决了Mark Wrang答案中的一个基本问题,但它对我也不起作用。
JSON字符串并不总是表示矩形数据集。它们可能包含不规则的数据。例如,Power BI活动日志输出包含不同的成员,取决于变量,如请求数据中发生的活动或当时可用的功能。
使用Piemol的评论,我处理了这个JSON:
[
    {
        "a":  "Value 1",
        "b":  20,
        "g":  "Arizona"
    },
    {
        "a":  "Value 2",
        "b":  40,
        "c":  "2022-01-01T11:00:00Z"
    },
    {
        "a":  "Value 3",
        "d":  "omicron",
        "c":  "2022-01-01T12:00:00Z"
    },
    {
        "a":  "Value 4",
        "b":  60,
        "d":  "delta",
        "e":  14,
        "c":  "2022-01-01T13:00:00Z"
    }
]

这个脚本生成了这个CSV文件:
"a","b","g"
"Value 1","20","Arizona"
"Value 2","40",
"Value 3",,
"Value 4","60",

请注意,缺少列c,d和e。看起来Export-CSV使用第一个传递的对象来确定要输出的CSV的模式。
为了处理这个问题,请使用UnifyProperties函数
function UnifyProperties {
  $Names = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
  $InputCollected = @($Input)
  $InputCollected.ForEach({ 
    foreach ($Name in $_.psobject.Properties.Name) { $Null = $Names.Add($Name) }
  })
  $inputCollected | Select-Object @($Names)
}

$pathToInputFolder = (New-Object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path + "\" + "PowerBIActivities\combined\"
$pathToInputFile = $pathToInputFolder + "Activities.json"
$pathToOutputFile = $pathToInputFolder + "Activities.csv"

$content = Get-Content -Path $pathToInputFile -Raw
$psObj = ConvertFrom-Json -InputObject $content

$psObj | UnifyProperties | Export-CSV $pathToOutputFile -NoTypeInformation

你正在过度复杂化它。像这个答案中展示的简单函数可以解决这个问题,并且更有效率。 - Santiago Squarzon
谢谢。如果您可以将我的回答示例中的内容工作起来,我很想看看它。我无法让它工作。此外,该函数有8行代码。它可能会取代我的5行代码吗?由于我是PowerShell新手,不确定我错在哪里。 - dougp
使用答案中的函数并假设您已将Json转换为对象,那么只需 $json | UnifyProperties | Export-Csv ... 就可以了。是的,这段代码更有效率,因为首先它只使用了1个循环,而您的代码使用了2个循环;其次,您正在使用 Add-Member 向对象添加属性,这是非常低效的。 - Santiago Squarzon
1
谢谢。这很容易。使用说明对我来说不太清楚。我试图使用它来组合我的数组中的对象对,而不仅仅是处理整个数组($json)。我会更新我的答案。 - dougp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接