从PSObject转换为Datatable

时间:2017-09-21 20:11:43

标签: powershell

基本上我正在通过http://www.webcal.fi/en-GB/other_file_formats.phpInvoke-WebRequest解析内容,并通过ConvertFrom-Json cmdlet将其从JSON转换为PSObject。

现在我需要将数据转换为SQL,我能想到的最有效的方法(能够重用已经存在的函数)是将PSObject转换为Datatable

我似乎无法想到任何简单的方法来实现这一点,同时保持通用,我不想将列名硬编码到我的数据表中,而是将它们从对象本身拉出来。有什么想法吗?

修改

MemberType      : Property
Value           : {@{date=2017-01-01; name=New Year's Day; url=https://en.wikipedia.org/wiki/New_Year%27s_Day; description=New Year's Day is observed on January 1, the first day of the year on the modern Gregorian calendar as well 
                  as the Julian calendar used in ancient Rome. With most countries using the Gregorian calendar as their main calendar, New Year's Day is the closest thing to being the world's only truly global public holiday, often 
                  celebrated with fireworks at the stroke of midnight as the new year starts. January 1 on the Julian calendar currently corresponds to January 14 on the Gregorian calendar, and it is on that date that followers of 
                  some of the Eastern Orthodox churches celebrate the New Year.}, @{date=2017-01-02; name=New Year's Day Holiday; url=https://en.wikipedia.org/wiki/New_Year%27s_Day; description=New Year's Day is observed on January 
                  1, the first day of the year on the modern Gregorian calendar as well as the Julian calendar used in ancient Rome. With most countries using the Gregorian calendar as their main calendar, New Year's Day is the 
                  closest thing to being the world's only truly global public holiday, often celebrated with fireworks at the stroke of midnight as the new year starts. January 1 on the Julian calendar currently corresponds to 
                  January 14 on the Gregorian calendar, and it is on that date that followers of some of the Eastern Orthodox churches celebrate the New Year.}, @{date=2017-04-14; name=Good Friday; 
                  url=https://en.wikipedia.org/wiki/Good_Friday; description=Good Friday (from the senses pious, holy of the word "good"), is a religious holiday observed primarily by Christians commemorating the crucifixion of 
                  Jesus Christ and his death at Calvary. The holiday is observed during Holy Week as part of the Paschal Triduum on the Friday preceding Easter Sunday, and may coincide with the Jewish observance of Passover. It is 
                  also known as Black Friday, Holy Friday, Great Friday, or Easter Friday, though the latter normally refers to the Friday in Easter week.}, @{date=2017-04-16; name=Easter; url=https://en.wikipedia.org/wiki/Easter; 
                  description=Easter (Old English: Ēostre; Greek: Πάσχα, Paskha; Aramaic: פֶּסחא‎ Pasḥa; from Hebrew: פֶּסַח‎ Pesaḥ) is the central feast in the Christian liturgical year. According to the Canonical gospels, Jesus 
                  rose from the dead on the third day after his crucifixion. His resurrection is celebrated on Easter Day or Easter Sunday (also Resurrection Day or Resurrection Sunday). The chronology of his death and resurrection 
                  is variously interpreted to have occurred between AD 26 and 36.}...}
IsSettable      : False
IsGettable      : True
TypeNameOfValue : System.Object
Name            : SyncRoot
IsInstance      : True

2 个答案:

答案 0 :(得分:3)

我不知道[datatable]是什么,因为我之前从未使用过它。似乎是ADO.NET的一部分。

但是,您可以通过编程方式获取[PSObject]的属性,使用隐藏的.PSObject属性,然后解析 .Properties属性。

此外,轻微的挑剔,您可以对您的URI使用Invoke-RestMethod,它会自动转发JSON的结果,因此您不会需要Invoke-WebRequest

答案 1 :(得分:1)

DataTable和PowerShell对象列表之间的主要区别在于,对于DataTable,所有项属性(包括项类型)对于每个“列”都是相同的,而PowerShell对象列表已定义所有属性与每个特定项目。这意味着PowerShell对象列表可以具有例如同一列中的DataTime对象和Int16,这在DataTable中是不可能的。

在这个已知的事实中,还有互联网上大多数当前可用的ConvertTo-DataTable类cmdlet的陷阱,因为它们仅在第一个对象(行)上设定DataTable的列类型。因此,如下所示的简单自定义对象会导致错误或将值错误地解析为字符串:

@(
    New-Object PSCustomObject -Property @{Name = "a"; Value = 123}
    New-Object PSCustomObject -Property @{Name = "b"; Value = 123456789012}
) | ConvertTo-DataTable

当第一个对象包含$ Null的项时会发生类似的问题,其中整个列通常被假定为String类型,但应该是例如日期时间类型:

@(
    New-Object PSCustomObject -Property @{Name = "a"; Date = $Null}
    New-Object PSCustomObject -Property @{Name = "b"; Date = Get-Date}
) | ConvertTo-DataTable

解决方案是找到列中所有对象的最佳拟合(最小)公共类型,这将花费时间并且并不总是那么简单。以此为例有两种类型,如UInt16Int16,您不能采用任何一种类型,因为一种类型不完全包含另一种类型。 UInt16的最小值为0,而Int16的最小值为-32768,而UInt16的最大值为65535Int16的最大值是32767。意思是,在这种情况下,最合适(最小)的常见类型既不是原始类型,也不是:UInt32Int32 *

ConvertTo-DataTable cmdlet将自动解析最适合(最小)的常见类型,并将其用于列类型。

*此处使用的cmdlet将首先根据类型找到首选项(已签名与未签名)

ConvertTo-DataTable

请参阅:https://powersnippets.com/convertto-datatable/

语法

<Object> | ConvertTo-DataTable [-ColumnType] <HashTable>

参数

[-Object] <Object>

要转换为DataTable的对象。

[-ColumnType] <HashTable>

按名称键入每列的定义:@{<ColumnName> = <Type>; ...}

实施例

将自定义对象转换为数据表

$MyObject =  @(
    New-Object PSCustomObject -Property @{Name = "a"; Value = 123;          Date = $Null}
    New-Object PSCustomObject -Property @{Name = "b"; Value = 123456789012; Date = $Now}
)
$DataTable = $MyObject | ConvertTo-DataTable

定义列类型:

$DataTable = $MyObject | ConvertTo-DataTable -ColumnType @{Name = [String]; Value = [Int64]; Date = [DateTime]}

转换(PowerShell)流程对象

$DataTable = Get-Process 'PowerShell' | ConvertTo-DataTable

转换用户语言列表

$DataTable = Get-WinUserLanguageList | ConvertTo-DataTable