需要在PowerShell中将嵌套的Json响应转换为csv

时间:2016-07-05 21:35:36

标签: json csv powershell

我有以下示例嵌套json响应,我需要将具有特定值的此响应转换为CSV文件。下面是嵌套的Json响应示例:

{
  "transaction": {
    "id": "TestTransID",
    "testCode": "NEW",
    "TestStatus": "SUCCESS",
    "client": {
      "TestNumber": "112112111"
    },
    "subject": {
      "individual": {
        "additionalAttributes": {
          "extraid": "787877878"
        },
        "addressList": [
          {
            "city": "New York",
            "country": {
              "name": "United States"
            },
            "postalCode": "123456789",
            "stateOrProvince": {
              "codeValue": "NY"
            }
          }
        ],
        "gender": "F",
        "identificationDocumentList": [
          {
            "number": "1214558520",
            "type": "TestId"
          }
        ],
        "name": {
          "firstName": "Qusay TestFull",
          "lastName": "TestLast",
          "middleName": "Middle 3"
        }
      }
    },
    "PROCESSConfiguration": {
      "id": 1
    },
    "testProductList": [
      {
        "product": {
          "id": 00,
          "name": "Test PROCESS",
          "productCode": "EFG",
          "disclaimer": "TestDisclaimer"
        },
        "testSourceResponseList": [
          {
            "testSource": {
              "id": 1,
              "name": "TEST"
            },
            "testSourceRecordList": [
              {
                "type": "TestRecord",
                "alertReasonCode": "TESTS",
                "alertReasonDescription": "ACTION LIST HIT - TEST",
                "testSource": "TEST",
                "varListNameFull": "TEST FULL NAME",
                "varListNameShort": "TEST SHORT",
                "varProgList": [
                  "SHORT"
                ],
                "varListId": "3421",
                "subject": {
                  "individual": {
                    "TestScore": {
                      "TestScore": 100,
                      "triggeredRule": "TestRule"
                    },
                    "aNameList": [
                      {
                        "fullName": " TestNameA",
                        "lastName": "TestNameA"
                      },
                      {
                        "firstName": "TestFirst",
                        "fullName": "TestFirst HUSAYN",
                        "lastName": "TestLast"
                      },
                      {
                        "firstName": "TestFirst",
                        "fullName": "TestFull",
                        "lastName": "TestLast"
                      },
                      {
                        "firstName": "TestFirst",
                        "fullName": "TestFull",
                        "lastName": "TestLast"
                      }
                    ],
                    "birthList": [
                      {
                        "dateOfBirth": "12 Apr 1910",
                        "dateOfBirthVerified": "true"
                      }
                    ],
                    "name": {
                      "firstName": "TestFirst",
                      "fullName": "TestFull",
                      "lastName": "TestLast"
                      },
                    "varNationality": [
                      {
                        "verified": "true"
                      }
                    ],
                    "remarks": "remark1"
                  }
                }
              },
              {
                "testSource": "TEST",
                "varListNameFull": "TEST FULL",
                "varListNameShort": "TEST SHORT",
                "varProgList": [
                  "XYZ"
                ],
                "varListId": "1234",
                "subject": {
                  "individual": {
                    "overallScore": {
                      "TestScore": 100,
                      "triggeredRule": "Testing"
                    },
                    "birthList": [
                      {
                        "dateOfBirth": "1965",
                      },
                      {
                        "dateOfBirth": "1966",
                      }
                    ],
                    "name": {
                      "firstName": "TestFirst",
                      "fullName": "TestFull",
                      "lastName": "TestLast",
                    },
                    "varNationality": [
                      {
                        "verified": "true"
                      }
                    ],
                    "remarks": "REMARK2"
                  }
                }
              }
            ]
          }
        ]
      }
    ],
  }
}

我需要接受来自"" PROCESSConfiguration":{           " id":1" 从第40行开始。如果您在记事本++中使用上面的代码。

另外,我需要关于var值的响应,比如名字,姓氏,全名,DOB等。

1 个答案:

答案 0 :(得分:0)

我仍然不确定要求的是什么。我假设您需要JSON文件中每个元素的完全限定路径。

我首先根据http://jsonlint.com/对JSON进行了一些小的调整。

基于此,我做了一个概念验证,适用于像您发布的JSON一样的OBJECT。它适用于这种情况。我包装了逻辑来处理多个对象,这些对象假设一个对象何时开始,下一个对象开始。此外,应该添加逻辑来处理包含多个属性的嵌套系列/数组(即Get-Process中的线程)来处理一般情况。带有值数组的单个元素(在本例中为.transaction.varProgList)通过在它们之间放置一个“;”来处理。

CSV文件假设所有对象都是对称的(具有相同的属性)。没有检查每个对象的属性是否与其他对象的属性对齐。请注意,嵌套系列的处理与此相关。您可以通过取消注释[System.Collections.ICollection]部分并尝试类似(Get-Process r*) | Select-Object Name,Threads | Expand-NestedProperty | Out-File .\t.csv -Width 100000

之类的内容来查看此示例

repro如下:$a是调整后的JSON内容,函数保存为Expand-NestedProperty.ps1。

# Load the function
. .\Expand-NestedProperty.ps1
# Create PowerShell object(s) based on the JSON
$b = $a | ConvertFrom-Json 
# Create a file with the CSV contents. 
$b | Expand-NestedProperty | Out-File -FilePath .\my.csv -Width 100000 

将其另存为Expand-NestedProperty.ps1

function Expand-NestedProperty {
    [CmdletBinding()]
    param (
        [Parameter( Position=0,
                    Mandatory=$true,
                    ValueFromPipeline=$true,
                    ValueFromPipelineByPropertyName=$true,
                    ValueFromRemainingArguments=$false,
                    HelpMessage='Object required...' )]
        $InputObject
    )
    begin {
        function ExpandNestedProperty {
            [CmdletBinding()]
            param (
                [Parameter( Position=0,
                            Mandatory=$true,
                            ValueFromPipeline=$true,
                            ValueFromPipelineByPropertyName=$true,
                            ValueFromRemainingArguments=$false,
                            HelpMessage='Object required...' )]
                $InputObject,
                [Parameter( Position=1,
                            Mandatory=$false,
                            ValueFromPipeline=$false,
                            ValueFromPipelineByPropertyName=$true,
                            ValueFromRemainingArguments=$false,
                            HelpMessage='String required...' )]
                [string]
                $FullyQualifiedName = ""
            )
            begin {
                $localResults =@()
                $FQN = $FullyQualifiedName
                $nestedProperties = $null
            }
            process {
                foreach ($obj in $InputObject.psobject.Properties) {
                    if ($(try {$obj.Value[0] -is [PSCustomObject]} catch {$false})) { # Catch 'Cannot index into a null array' for null values
                        # Nested properties
                        $FQN = "$($FullyQualifiedName).$($obj.Name)"
                        $nestedProperties = $obj.value | ExpandNestedProperty -FullyQualifiedName $FQN
                    }
                    elseif ($obj.Value -is [array]) {
                        # Array property
                        $FQN = "$($FullyQualifiedName).$($obj.Name)"
                        [psobject]$nestedProperties = @{
                            $FQN = ($obj.Value -join ';')
                        }
                    }
                    # Example of how to deal with generic case. 
                    # This needed for the Get-Process values ([System.Collections.ReadOnlyCollectionBase] and [System.Diagnostics.FileVersionInfo]) that are not [array] collection type.
<#
                    elseif ($obj.Value -is [System.Collections.ICollection]) { 
                        # Nested properties
                        $FQN = "$($FullyQualifiedName).$($obj.Name)"
                        $nestedProperties = $obj.value | ExpandNestedProperty -FullyQualifiedName $FQN
                    }
#>
                    else { # ($obj -is [PSNoteProperty]) for this case, but could be any type
                        $FQN = "$($FullyQualifiedName).$($obj.Name)"
                        [psobject]$nestedProperties = @{
                            $FQN = $obj.Value
                        }
                    }
                    $localResults += $nestedProperties
                } #foreach $obj
            }
            end {
                [pscustomobject]$localResults
            }
        } # function ExpandNestedProperty
        $objectNumber = 0
        $firstObject = @()
        $otherObjects = @()
    }
    process {
        if ($objectNumber -eq 0) {
            $objectNumber++
            $firstObject = $InputObject[0] | ExpandNestedProperty
        }
        else {
            if ($InputObject -is [array]) {
                foreach ($nextInputObject in $InputObject[1..-1]) {
                    $objectNumber++
                    $otherObjects += ,($nextInputObject | ExpandNestedProperty)
                }
            }
            else {
                $objectNumber++
                $otherObjects += ,($InputObject | ExpandNestedProperty)
            }
        }
    }
    end {
        # Output CSV header and a line for each object which was the specific requirement here.  
        # Could create an array of objects using $firstObject + $otherObjects that is then piped to Export-CSV if we want a generic case.
        Write-Output "`"$($firstObject.Keys -join '","')`""
        Write-Output "`"$($firstObject.Values -join '","')`""
        foreach ($otherObject in $otherObjects) {
            Write-Output "`"$($otherObject.Values -join '","')`""
        }
    }
} # function Expand-NestedProperty