20

在转换大小超过 2MB 的 JSON 字符串时,我在使用 PowerShell v3 时遇到问题。PowerShell 使用的 JSON 序列化程序的默认限制设置为 2MB,这解释了错误。

但是,当我在较小的集合上使用 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 中的对象类型?

4

4 回答 4

22

我遇到了同样的问题,并且能够像这样解决它:

[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.MaxJsonLengthMaxJsonLength 属性来操作

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

于 2014-11-25T11:08:18.653 回答
6

Invoke-RestMethod在结果中使用大型 JSON 集合时,我遇到了同样的问题。我最终调整了Parsing json with PowerShell 和 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)
}
于 2015-02-19T08:39:35.330 回答
1

多年来,这个对我很有用:

Add-Type -Assembly System.Web.Extensions

function get-Json($data) {
    $json = [System.Web.Script.Serialization.JavaScriptSerializer]::new()
    $json.MaxJsonLength = 104857600
    $out = $json.Deserialize($data, [System.Object])
    return $out
}
于 2020-07-07T13:45:53.783 回答
0

我把它放在我的代码中:

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

其中 ws_Out.GetType() 是我定义的用于解析 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
于 2013-05-31T10:28:09.440 回答