如何将此嵌套的JSON转换为Datatable

时间:2019-04-05 08:54:52

标签: json powershell

[{
    "change": {
        "action": "updated",
        "record_id": 71176961,
        "record": {
            "time_entry": {
                "date_at": "2019-04-04",
                "minutes": 197
            }
        }
    }
}, {
    "change": {
        "action": "created",
        "record_id": 71209354,
        "record": {
            "time_entry": {
                "date_at": "2019-04-04",
                "minutes": 15
            }
        }
    }
}]

我需要将此json转换为2D powershell data table,以便可以将bulkcopy转换为database table。所以我在json中有2个级别(3D)(更改并记录更改中)。我可以做类似的事情(从json转换后):

.change | Select-Object action, record_id, @{n='date_at';e={$_.record.time_entry.date_at}}, @{n='minutes';e={$_.record.time_entry.minutes}}| Out-DataTable

但问题是,记录实体可能真的很大(并且会增长),我不想在代码中指定所有名称。因此,我想将第二级(记录)转换为数据表,并在代码中包含change.action,change.record_id(因为“ change”结构永远不会改变,但“ record”结构会改变)。

1 个答案:

答案 0 :(得分:0)

这对我有用:

$object = @"
[{
    "change": {
        "action": "updated",
        "record_id": 71176961,
        "record": {
            "time_entry": {
                "date_at": "2019-04-04",
                "minutes": 197
            }
        }
    }
}, {
    "change": {
        "action": "created",
        "record_id": 71209354,
        "record": {
            "time_entry": {
                "date_at": "2019-04-04",
                "minutes": 15
            }
        }
    }
}]
"@ | ConvertFrom-Json 


    #------------------------------------------------------------------------
    function Get-DataTable
    #------------------------------------------------------------------------
    {

        param(
            [PSCustomObject]$srcObject,
            [System.Data.DataTable]$dt,
            [System.Data.DataRow]$row = $null
        )

        foreach( $property in $srcObject.PSObject.Properties ) {

            if( $property.Value -is [PSCustomObject] ) {
                $row = (Get-DataTable -srcObject $property.Value -dt $dt -row $row).Row
            }
            else {
                if( $row -eq $null ) {
                    if( $dt.Columns.IndexOf($property.Name) -lt 0 ) {
                        [void]$dt.Columns.Add($property.Name, [string]::Empty.GetType() )
                    }
                }
                else {
                    $row.Item($property.Name) = $property.value
                }

            }
        }

        return @{ 'Row' = $row }
    }

    $dt = New-Object System.Data.DataTable

    # create columns
    foreach( $item in $object ) {
        Get-DataTable -srcObject $item -dt $dt | out-null
    }

    # fill datatable
    foreach( $item in $object ) {
        $row = $dt.NewRow()
        $row = (Get-DataTable -srcObject $item -dt $dt -row $row).Row
        [void]$dt.Rows.Add( $row )
    }

    $dt