假设我有一个PSObject
,其中包含一个整数和一个我要序列化为JSON的日期,并且收件人能够对其进行反序列化。在Javascript中执行此操作,我得到以下JSON:
JSON.stringify({Date: new Date(), Number: 23})
"{"Date":"2014-09-10T14:11:27.092Z","Number":23}"
JSON.parse(JSON.stringify({Date: new Date(), Number: 23}))
>> Object {Date: "2014-09-10T14:13:28.950Z", Number: 23}
看起来非常标准的JSON,可以通过javascript正确解释。
但是,看来powershell的ConvertTo-Json
与DateTime
序列化如此不一致,以至于它甚至无法正确地来回转换。为了充分说明这一点:
PS C:\dev> $testObj = New-Object -TypeName PSobject -Property @{ Date = Get-Date; Number = 23; }
PS C:\dev> $testObj
Number Date
------ ----
23 9/10/2014 9:52:14 AM
PS C:\dev\git\strawman> $testObj | ConvertTo-Json
{
"Number": 23,
"Date": {
"value": "\/Date(1410357134361)\/",
"DisplayHint": 2,
"DateTime": "Wednesday, September 10, 2014 9:52:14 AM"
}
}
PS C:\dev> $testObj | ConvertTo-Json | ConvertFrom-Json
Number Date
------ ----
23 @{value=9/10/2014 1:52:14 PM; DisplayHint=2; DateTime=Wednesday, September 10, 2014 9:52:14 AM}
它不仅为日期属性生成的JSON根本无效,而且无法通过javascript正确解释,但是PowerShell的ConvertFrom-Json
甚至无法正确解释它给它看起来相同的物体。
有没有办法正确地将PSObject
DateTime
序列化为有效的json,可以被收件人正确反序列化?
答案 0 :(得分:2)
我最终快速编写了一个函数来将任何PSObject转换为可以转换为更干净的JSON的PSObject:
<#
.SYNOPSIS
Creates a new PSObject where all properties of the original object that are not able to be
properly serialized to JSON are converted to a value which can be properly converted to JSON.
This includes the following types:
* DateTime
This conducts a deep property search
.Example
Convert an custom PSObject to have parsable dates in Json
$customObject = New-Object -TypeName PSobject -Property @{ Date = Get-Date; Number = 23; InnerDate = New-Object -TypeName PSObject -Property @{Date=Get-Date;} }
## BAD Json
PS C:\dev> $customObject | ConvertTo-Json
{
"Date": {
"value": "\/Date(1410372629047)\/",
"DisplayHint": 2,
"DateTime": "Wednesday, September 10, 2014 2:10:29 PM"
},
"Number": 23,
"InnerDate": {
"Date": {
"value": "\/Date(1410372629047)\/",
"DisplayHint": 2,
"DateTime": "Wednesday, September 10, 2014 2:10:29 PM"
}
}
}
## Good Json
PS C:\dev> $customObject | ConvertTo-JsonifiablePSObject | ConvertTo-Json
{
"Date": "2014-09-10T14:10:29.0477785-04:00",
"Number": 23,
"InnerDate": {
"Date": "2014-09-10T14:10:29.0477785-04:00"
}
}
#>
function ConvertTo-JsonifiablePSObject
{
param
(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[PSObject]$Object
)
$newObjectProperties = @{}
foreach ($property in $Object.psobject.properties)
{
$value = $property.Value
if ($property.TypeNameOfValue -eq "System.Management.Automation.PSCustomObject")
{
$value = ConvertTo-JsonifiablePSObject -Object $property.Value
}
elseif ($property.TypeNameOfValue -eq "System.DateTime")
{
$value = $property.Value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK")
}
$newObjectProperties[$property.Name] = $value
}
return New-Object -TypeName PSObject -Property $newObjectProperties
}