2014-09-10 55 views
1

可以說我有一個PSObject,它帶有一個整數和一個我想要序列化爲JSON的日期,並讓收件人能夠反序列化它。在Javascript中這樣做,我得到以下JSON:如何正確將具有DateTime的PSObject序列化爲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-JsonDateTime序列化很不一致,它甚至不能正確地來回轉換自己。爲了充分說明這一點:

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} 

它不僅是生產的日期財產完全無效且無法通過JavaScript的正確解釋,但PowerShell的ConvertFrom-Json甚至不能正確地解釋它,給它的JSON相同的對象回來。

有沒有什麼辦法可以將PSObjectDateTime正確序列化爲有效的json,並且可以被收件人正確地反序列化呢?

+0

你可能想看看這裏:http://stackoverflow.com/questions/ 206384/how-to-format-a-microsoft-json-date – 2014-09-10 14:47:25

+0

這並不能解決序列化問題,它只嘗試回答與此無關的反序列化問題。 – KallDrexx 2014-09-10 14:52:09

+0

您不需要自定義對象看到這個。 'Get-Date | ConvertTo-Json | ConvertFrom-Json'爲您提供了一個具有三個屬性的自定義對象:value,DisplayHint和DateTime。這個例子實際上是在ConvertFrom-Json的文檔中,所以我猜測這種行爲是通過設計的。坦白地說,這種行爲是奇怪的,但我不認爲.NET從來沒有把DateTime序列化處理成JSON特別好。部分問題是DateTime中沒有JSON類型,所以你做的任何事都只是約定。目前的約定是使用ISO 8601格式,但沒有規定。 – 2014-09-10 16:53:11

回答

0

最後我趕緊寫了一個函數,任何PSObject轉換爲PSObject可以改用清潔JSON:

<# 
.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 
}