簡體   English   中英

Powershell 嵌套 JSON 到 csv 轉換

[英]Powershell nested JSON to csv conversion

我有一個相當奇特的嵌套 JSON 在某些情況下,鍵值對正常出現,但在其他情況下,鍵的類型出現在進一步的嵌套中。

{"metadata":{"systemId":"da1895","legalEntity":"A0"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G32"},"seg":{"string":"S"},"strike":{"double":4.4}}}
{"metadata":{"systemId":"45364d","legalEntity":"5G"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G81"},"seg":{"string":"S"},"strike":{"double":5.0}}}

在示例中,您可以看到metadata的字段是簡單的鍵值對,但在recordContent下,我們有positionDate它是簡單的鍵值,但"account":{"string":"G32"}"strike":{"double":4.4}不是。

我想放棄類型信息並到達 CSV 結構,如下所示:

systemId, legalEntity, positionDate,         account,seg,strike
da1895,   A0,          2019-04-08 00:00:00.0,G32,    S,  4.4
4536d,    5G,          2019-04-08 00:00:00.0,G81,    S,  5.0

關於如何使用 Powershell 將這樣的結構轉換為 CSV 的任何想法?

這是我嘗試過的:

$TemplateParametersFile = "c:\data\output.json"
$JsonParameters = Get-Content $TemplateParametersFile | ConvertFrom-Json

$metadatafields = $JsonParameters.metadata[0].PSObject.Properties.Name
$recordcontentfields = $JsonParameters.recordContent[0].PsObject.Properties.Name

$oData = New-Object PSObject

$metadatafields |
ForEach {
    Add-Member -InputObject $oData -NotePropertyName ($_) -NotePropertyValue $JsonParameters.metadata.($_)
}

$recordcontentfields |
ForEach {
    Add-Member -InputObject $oData -NotePropertyName ($_) -NotePropertyValue $JsonParameters.recordContent.($_)
}

這給了我:

$oData

systemId     : {da1895, 45364d}
legalEntity  : {A0, 5G}
positionDate : {2019-04-08 00:00:00.0, 2019-04-08 00:00:00.0}
account      : {@{string=G32}, @{string=G81}}
seg          : {@{string=S}, @{string=S}}
strike       : {@{double=4.4}, @{double=5.0}}

我現在有點卡住了,上面沒有轉換為 csv。

請注意,除了元數據和記錄內容之外,我沒有硬編碼任何字段名,並且我想保持這種靈活性,以防 JSON 結構發生變化。

謝謝

嘗試這個:

$data = ConvertFrom-Json @"
[
{"metadata":{"systemId":"da1895","legalEntity":"A0"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G32"},"seg":{"string":"S"},"strike":{"double":4.4}}},
{"metadata":{"systemId":"45364d","legalEntity":"5G"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G81"},"seg":{"string":"S"},"strike":{"double":5.0}}}
]
"@

$data | Select-Object -Property @{l="systemId"; e={$_.metadata.systemId}}, @{l="legalEntity"; e={$_.metadata.legalEntity}},
@{l="positionDate"; e={$_.recordContent.positionDate}}, @{l="account"; e={$_.recordContent.account.string}},
@{l="seg"; e={$_.recordContent.seg.string}}, @{l="strike"; e={$_.recordContent.strike.double}} | Export-Csv

這應該適用於任何嵌套的 psobject。

$json = @'
{"metadata":{"systemId":"da1895","legalEntity":"A0"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G32"},"seg":{"string":"S"},"strike":{"double":4.4}}}

'@
$obj = ConvertFrom-Json $json


$obj.recordContent | gm -MemberType NoteProperty | % {
    $prop = $_.name
    if ($obj.recordContent.$prop.GetType().name -eq 'pscustomobject') {
        $obj.recordContent.$prop = $obj.recordContent.$prop.psobject.Members | where membertype -eq noteproperty | select -ExpandProperty value
    }
    $obj.metadata | add-member -MemberType NoteProperty -Name $prop -Value $obj.recordContent.$prop

}
$newobj = $obj.metadata
$newobj

我建議在有序哈希表( [ordered] @{} ) 中迭代地收集屬性-名稱-值對,然后可以將其轉換為[pscustomobject]以將其轉換為自定義 object。

以下解決方案中沒有硬編碼屬性名稱,但假定對象圖結構遵循示例 JSON 中的模式。

反射(屬性名稱和值的發現)是通過 PowerShell 在所有對象上提供的內在.psobject屬性執行的。

# Parse sample JSON into an array of [pscustomobject] graphs.
$fromJson = ConvertFrom-Json @'
[
  {"metadata":{"systemId":"da1895","legalEntity":"A0"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G32"},"seg":{"string":"S"},"strike":{"double":4.4}}}
  ,
  {"metadata":{"systemId":"45364d","legalEntity":"5G"},"recordContent":{"positionDate":"2019-04-08 00:00:00.0","account":{"string":"G81"},"seg":{"string":"S"},"strike":{"double":5.0}}}
]
'@

# Initialize an aux. ordered hashtable to collect the property-name-value
# pairs in.
$oht = [ordered] @{}

$fromJson | ForEach-Object {
    $oht.Clear()
    # Loop over top-level properties.
    foreach ($topLevelProp in $_.psobject.Properties) {
      # Loop over second-level properties.
      foreach ($prop in $topLevelProp.Value.psobject.Properties) {
        if ($prop.Value -is [System.Management.Automation.PSCustomObject]) {
          # A nested value: Use the value of the (presumed to be one-and-only)
          #                 property of the object stored in the value.
          $oht[$prop.Name] = $prop.Value.psobject.Properties.Value
        }
        else {
          # A non-nested value: use as-is.
          $oht[$prop.Name] = $prop.Value
        }
      }
    }
    # Construct and output a [pscustomobject] from the aux. ordered hashtble.
    [pscustomobject] $oht
  } |
      ConvertTo-Csv  # Replace this with Export-Csv to export to a file.

以上產生:

"systemId","legalEntity","positionDate","account","seg","strike"
"da1895","A0","2019-04-08 00:00:00.0","G32","S","4.4"
"45364d","5G","2019-04-08 00:00:00.0","G81","S","5"

幾年前,我為此寫了一個可重用的Flatten-Object function。
唯一的區別是它將(子)屬性名稱與父屬性名稱組合在一起,因為它們可能不是唯一的:

$JsonParameters |Flatten-Object |Format-Table

metadata.systemId metadata.legalEntity recordContent.positionDate recordContent.account.string recordContent.seg.string recordContent.strike.double
----------------- -------------------- -------------------------- ---------------------------- ------------------------ ---------------------------
da1895            A0                   2019-04-08 00:00:00.0      G32                          S                                                4.4
45364d            5G                   2019-04-08 00:00:00.0      G81                          S                                                  5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM