【问题标题】:Flatten a nested JSON with array and filter to CSV使用数组和过滤器将嵌套 JSON 展平为 CSV
【发布时间】:2022-03-16 17:15:05
【问题描述】:

我有一个关于 如何使用 Powershell 将嵌套的 JSON 展平并转换为 CSV。 下面是我的 JSON,它是从 Office 365 获取的包含许多用户消息的邮件消息日志,我需要过滤列、展平并转换为 CSV:

createdDateTime,
receivedDateTime,
from_name
from_adress
To_name_1
To_adress_2
To_name_2
To_adress_2
...

“发件人”字段只有一个数据。 但是“toRecipients”是一个数组。

{
  ...
  "createdDateTime": "xxxx-xx-xx",
  "receivedDateTime": "xxxx-xx-xx",
  "isRead": true,
  "from": {
    "emailAddress": {
      "name": "John",
      "adress": "john@onmicrosoftware.com"
    }
  },
  "toRecipients": [
    {
      "emailAddress": {
        "name": "Amy",
        "adress": "Amy@onmicrosoftware.com"
      }
    },
    {
      "emailAddress": {
        "name": "Amy",
        "adress": "Amy@onmicrosoftware.com"
      }
    }
  ]
}

【问题讨论】:

  • 嗨,如果我理解正确,您的过滤器可以正常工作,并且您无法将结果导出为 CSV,对吧?这对你有帮助吗(?):convert-json-to-csv-using-powershell - 如果你不能使用这篇文章中提到的解决方案,我会尝试创建第二个数组并通过创建一个新的 PSObject 来保存过滤后的 json 输入:$obj = New-Object PSObject
  • 看看CsvCruncher,虽然它不支持通过嵌套数组。

标签: json powershell office365


【解决方案1】:

这是一个完整的可运行示例。它将创建一个文件“C:\test.csv”。

没有将嵌套对象展平为平面对象的“自动”方式。但是您可以手动为平面对象创建分配属性。

首先我将 JSON 文本解析为一个 powershell 对象

$obj = @"
{
  "createdDateTime": "xxxx-xx-xx",
  "receivedDateTime": "xxxx-xx-xx",
  "isRead": true,
  "from": {
    "emailAddress": {
      "name": "John",
      "adress": "john@onmicrosoftware.com"
    }
  },
  "toRecipients": [
    {
      "emailAddress": {
        "name": "Amy",
        "adress": "Amy@onmicrosoftware.com"
      }
    },
    {
      "emailAddress": {
        "name": "Amy",
        "adress": "Amy@onmicrosoftware.com"
      }
    }
  ]
}
"@ | ConvertFrom-Json

现在获取 Powershell 对象(或对象列表,即使您有很多这样的条目也可以使用)并将其通过管道传递给 ForEach-Object。在循环内部将不同的属性映射到一个平面对象。

$flattened = $obj | ForEach-Object {
    return [PSCustomObject]@{
        createdDateTime = $_.createdDateTime
        receivedDateTime = $_.receivedDateTime
        from_name = $_.from.emailAddress.name
        from_adress = $_.from.emailAddress.adress
        to_name_1 = $_.toRecipients[0].emailAddress.name
        to_adress_1 = $_.toRecipients[0].emailAddress.adress
        to_name_2 = $_.toRecipients[1].emailAddress.name
        to_adress_2 = $_.toRecipients[1].emailAddress.adress
    }
}

现在您可以将整个内容导出为 CSV

$flattened | Export-Csv C:\test.csv -Delimiter ";" -Encoding UTF8

这假设总是有 2 个 toRecipients。如果遇到更多,可以动态添加 to_name_3、to_name_4 等,但这有点复杂。

【讨论】:

  • 感谢 Cbsch 的正确回复,真的很有帮助。是的,这将是一个问题,并且变得过于复杂而无法动态获取收件人。如果我只需要将所有嵌套的 toRecipients 数组上下文保存到 CSV 中的一列以进行进一步分析,该怎么办?
  • 那会更容易做到。例如,$_.toRecipients.emailAddress.adress -join ', ' 会将所有电子邮件地址作为一个字符串值提供给您,地址之间用逗号分隔。
  • 非常感谢 Cbsch。我按照上面的方法尝试了您的建议,'To_EmailAddress' = $_.toRecipients.emailAddress.address -join ', ' 但这很奇怪,如下所示,因为其他字段完美返回“System.Object&, mscorlib, Version=4.0.0.0, Culture =neutral, PublicKeyToken=b77a5c561934e089 Address(int)" 作为替代方法,我只是请求可以将“toRecipients”的所有原始数据返回到一个 CSV 列,如果可能的话,它也适用于我。非常感谢您的建议。
猜你喜欢
  • 2018-01-16
  • 2021-12-31
  • 2016-10-01
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 2022-11-29
相关资源
最近更新 更多