2013-05-31 41 views
13

我在使用PowerShell v3轉換2MB大小的JSON字符串時遇到問題。 PowerShell使用的JSON序列化程序中的默認限制設置爲2MB,這解釋了錯誤。ConvertFrom-Json最大長度

然而,當我在一個較小的一套使用ConvertFrom JSON的序列化對象(我用小和更大的內部收集各種數據對象,但那些都是相同的對象),它返回非常漂亮的物體,我可以很容易地訪問所有屬性。

爲了克服我試圖用手反序列化數據串行器的侷限性:

$jsser = New-Object System.Web.Script.Serialization.JavaScriptSerializer 
$jsser.MaxJsonLength = $jsser.MaxJsonLength * 10 
$jsser.RecursionLimit = 99  

$outObject = $jsser.DeserializeObject($json) 

對象看起來不同,似乎內部集合並沒有反序列化,當我嘗試執行性質,因爲它們返回空的結果。

我的問題:

  1. 假設是ConvertFrom-Json做一些額外的魔法或以某種方式創建序列化對象之前的模板。任何想法如何複製它?

  2. 我得到的對象始終是PSCustomObject;如果我得到我想要設置的對象ConvertFrom-Json是否有用它作爲JsonSerializer中的對象類型?

回答

0

我把這個在我的代碼:

 JavaScriptSerializer oSerializer = new JavaScriptSerializer(); 
    oSerializer.MaxJsonLength *= 2; 
    ws_Out = (ClsWsOut)oSerializer.Deserialize(jsonOut, ws_Out.GetType()); 

凡ws_Out.GetType()是一個CLASSE我定義解析JSON。

public class ClsLogin_In :ClsWsIn 
{ 
    public string login { get; set; } 
    public string passwd { get; set; } 
} 

public class ClsLogin_Out : ClsWsOut 
{ 
    public int error { get; set; } 
    public string error_desc { get; set; } 
    public int key { get; set; } 
} 

編輯

在PowerShell中V3時,由Web服務返回的JSON是非常大的PowerShell的V3正在發送異常。 因此,我使用XML序列化,這裏是我的功能,它也使用外部程序集,但它們是基本程序集,XML有點冗長,但它有效。

Add-Type -AssemblyName System.ServiceModel.Web, System.Runtime.Serialization 
$utf8 = [System.Text.Encoding]::UTF8  

function Write-String 

{ 
    PARAM([Parameter()]$stream, 
     [Parameter(ValueFromPipeline=$true)]$string) 

    PROCESS 
    { 
    $bytes = $utf8.GetBytes($string) 
    $stream.Write($bytes, 0, $bytes.Length) 
    } 
} 

function Convert-JsonToXml 

{ 
    PARAM([Parameter(ValueFromPipeline=$true)][string[]]$json) 

    BEGIN 
    { 
    $mStream = New-Object System.IO.MemoryStream 
    } 

    PROCESS 
    { 
    $json | Write-String -stream $mStream 
    } 

    END 
    { 
    $mStream.Position = 0 
    try 
    { 
     $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($mStream,[System.Xml.XmlDictionaryReaderQuotas]::Max) 
     $xml = New-Object Xml.XmlDocument 
     $xml.Load($jsonReader) 
     $xml 
    } 
    finally 
    { 
     $jsonReader.Close() 
     $mStream.Dispose() 
    } 
    } 
} 

function Convert-XmlToJson 
{ 
    PARAM([Parameter(ValueFromPipeline=$true)][Xml]$xml) 

    PROCESS 
    { 
    $mStream = New-Object System.IO.MemoryStream 
    $jsonWriter = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonWriter($mStream) 
    try 
    { 
     $xml.Save($jsonWriter) 
     $bytes = $mStream.ToArray() 
     [System.Text.Encoding]::UTF8.GetString($bytes,0,$bytes.Length) 
    } 
    finally 
    { 
     $jsonWriter.Close() 
     $mStream.Dispose() 
    } 
    } 
} 

這裏是一個例子。

$json = @' 
{ 
    "data": { 
    "langid": 7, 
    "results": [{ 
     "first_aired": "2010-11-15", 
     "name": "Accused", 
     "tvdbid": 72663 
     }, 
     { 
     "first_aired": "2010-01-17", 
     "name": "Enzai: Falsely Accused", 
     "tvdbid": 135881 
     }] 
    }, 
    "message": "", 
    "result": "success" 
} 
'@ 

$xmlOut = Convert-JsonToXml -json $json 
($xmlOut.root.data.results).ChildNodes[0].tvdbid.InnerText 
($xmlOut.root.data.results).ChildNodes[1].tvdbid.InnerText 
+0

是的但在PowerShell中我試圖避免導入。Net dlls Powershell擁有自己的動態對象,這些動態對象在運行時會與屬性一起填充,並且在2MB以下的文件下工作良好。我只是想強制它以2MB以上的文件以相同的方式工作。 – Jammes

+0

要成爲完整的PowerShell,您可以使用XML。我在PowerShell V2.0腳本中使用它。它支持大的jsons,但使用起來有點冗長。 – JPBlanc

+0

如果你看看我的原始問題,我已經找到了反序列化大型JSON的方法。當你自己實例化序列化程序時,你可以改變MaxJsonLength屬性。您必須使用Invoke-WebRequest而不是Invoke-RestRequest,而不是跟隨RawContent並查找第一個「{」並從infront中刪除所有內容,並且您有一個乾淨的json。在大對象上,這個Xml序列化可能會帶來收益。 – Jammes

16

我有同樣的問題,並能解決這個問題是這樣的:

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")   
$jsonserial= New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer 
$jsonserial.MaxJsonLength = 67108864 
$Obj = $jsonserial.DeserializeObject($CourseTypesResponse) 

您可以使用$jsonserial.MaxJsonLength操縱MaxJsonLength財產

來源:https://social.technet.microsoft.com/Forums/windowsserver/en-US/833c99c1-d8eb-400d-bf58-38f7265b4b0e/error-when-converting-from-json?forum=winserverpowershell&prof=required

3

我在結果中使用Invoke-RestMethod和大型JSON集合時會出現相同的問題。我最終調整了Parsing json with PowerShell and Json.NET中的方法將JSON集合轉換爲PowerShell對象。

# .NET JSON Serializer 
    $global:javaScriptSerializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer 
    $global:javaScriptSerializer.MaxJsonLength = [System.Int32]::MaxValue 
    $global:javaScriptSerializer.RecursionLimit = 99 

    # Functions necessary to parse JSON output from .NET serializer to PowerShell Objects 
    function ParseItem($jsonItem) { 
      if($jsonItem.PSObject.TypeNames -match "Array") { 
        return ParseJsonArray($jsonItem) 
      } 
      elseif($jsonItem.PSObject.TypeNames -match "Dictionary") { 
        return ParseJsonObject([HashTable]$jsonItem) 
      } 
      else { 
        return $jsonItem 
      } 
    } 

    function ParseJsonObject($jsonObj) { 
      $result = New-Object -TypeName PSCustomObject 
      foreach ($key in $jsonObj.Keys) { 
        $item = $jsonObj[$key] 
        if ($item) { 
          $parsedItem = ParseItem $item 
        } else { 
          $parsedItem = $null 
        } 
        $result | Add-Member -MemberType NoteProperty -Name $key -Value $parsedItem 
      } 
      return $result 
    } 

    function ParseJsonArray($jsonArray) { 
      $result = @() 
      $jsonArray | ForEach-Object { 
        $result += , (ParseItem $_) 
      } 
      return $result 
    } 

    function ParseJsonString($json) { 
      $config = $javaScriptSerializer.DeserializeObject($json) 
      return ParseJsonObject($config) 
    } 
+0

感謝您的解決方案。但是,最好用'返回ParseItem($ config)'替換'返回ParseJsonObject($ config)',因爲'DeserializeObject'可能會返回數組。 –