2013-05-31 30 views
13

Tôi gặp sự cố khi sử dụng PowerShell v3 khi chuyển đổi chuỗi JSON có kích thước trên 2MB. Giới hạn mặc định trong trình nối tiếp JSON được PowerShell sử dụng được đặt thành 2MB, giải thích lỗi này.ConvertFrom-Json max length

Tuy nhiên khi tôi deserialize đối tượng bằng cách sử dụng ConvertFrom-Json trên một tập nhỏ hơn (tôi nhận các đối tượng dữ liệu khác nhau với bộ sưu tập nội bộ nhỏ hơn và lớn hơn nhưng đó là những đối tượng tương tự) nó trả về đối tượng rất đẹp với tất cả các thuộc tính mà tôi có thể dễ dàng truy cập.

Để khắc phục những hạn chế của serializer Tôi cố gắng để deserialize dữ liệu bằng tay:

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

$outObject = $jsser.DeserializeObject($json) 

Đối tượng trông khác nhau có vẻ như bộ sưu tập nội bộ không được deserialized và khi tôi cố gắng để thực hiện tính họ trả lại kết quả trống.

Câu hỏi của tôi:

  1. Assumption là ConvertFrom-Json hiện một số phép thuật bổ sung hoặc bằng cách nào đó tạo ra một khuôn mẫu cho các đối tượng trước khi serialization. Bất kỳ ý tưởng làm thế nào để tái tạo nó?

  2. Đối tượng tôi nhận được luôn là PSCustomObject; nếu tôi nhận được các đối tượng tôi muốn thiết lập bởi ConvertFrom-Json là có anyway để sử dụng nó như là loại đối tượng trong JsonSerializer?

Trả lời

0

tôi đặt điều này trong mã của tôi:

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

đâu ws_Out.GetType() là một classe tôi xác định để phân tích 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; } 
} 

Sửa

trong PowerShell V3 khi json trả về bởi một dịch vụ web là rất lớn các PowerShell V3 đang gửi một ngoại lệ. Vì vậy, tôi sử dụng serialization XML, đây là chức năng của tôi, nó cũng sử dụng một hội đồng bên ngoài, nhưng họ là những người cơ bản, XML là một chút tiết nhưng nó hoạt động.

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() 
    } 
    } 
} 

Dưới đây là ví dụ.

$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

Có nhưng trong PowerShell tôi đang cố gắng tránh nhập.Net dlls Powershell có các đối tượng động riêng của nó được phổ biến với các thuộc tính khi đang di chuyển và nó hoạt động tốt với các tệp dưới 2MB. Tôi chỉ muốn ép nó hoạt động theo cùng cách với các tệp trên 2MB. – Jammes

+0

Để có đầy đủ PowerShell, bạn có thể sử dụng XML. Tôi sử dụng nó trong các kịch bản PowerShell V2.0 của mình. Nó hỗ trợ jsons lớn, nhưng nó là một chút tiết để sử dụng. – JPBlanc

+0

Nếu bạn nhìn vào câu hỏi ban đầu của tôi, tôi đã tìm thấy một cách để deserialize JSON lớn. Khi bạn khởi tạo trình tự tuần tự, bạn có thể thay đổi thuộc tính MaxJsonLength. Bạn sẽ phải sử dụng Invoke-WebRequest chứ không phải là Invoke-RestRequest và làm theo RawContent và tìm kiếm '{' đầu tiên và loại bỏ mọi thứ khỏi infront và bạn có một json sạch. Trên các đối tượng lớn, xml serialization này có thể mất phí. – Jammes

16

tôi đã cùng một vấn đề và đã có thể giải quyết nó như thế này:

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

Bạn có thể sử dụng $jsonserial.MaxJsonLength để thao tác các tài sản MaxJsonLength

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

3

tôi đã cùng một mệnh đề khi sử dụng Invoke-RestMethod và các bộ sưu tập JSON lớn trong kết quả. Cuối cùng tôi đã điều chỉnh các phương thức từ Parsing json with PowerShell and Json.NET để chuyển đổi Bộ sưu tập JSON thành các đối tượng 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

Cảm ơn giải pháp. Tuy nhiên, tốt hơn nên thay thế 'return ParseJsonObject ($ config)' bằng 'return ParseItem ($ config)' thành 'DeserializeObject' có thể trả về mảng. –

Các vấn đề liên quan