从Json转换最大长度
在转换大小超过2MB的JSON字符串时,我在使用PowerShell v3时遇到问题。PowerShell使用的JSON序列化程序中的默认限制设置为2MB,这解释了错误 然而,当我在一个较小的集合上使用ConvertFrom Json反序列化对象时(我得到了各种具有越来越小的内部集合的数据对象,但这些都是相同的对象),它返回了非常好的对象,其中包含我可以轻松访问的所有属性 为了克服序列化程序的限制,我尝试手动反序列化数据:从Json转换最大长度,json,powershell,Json,Powershell,在转换大小超过2MB的JSON字符串时,我在使用PowerShell v3时遇到问题。PowerShell使用的JSON序列化程序中的默认限制设置为2MB,这解释了错误 然而,当我在一个较小的集合上使用ConvertFrom Json反序列化对象时(我得到了各种具有越来越小的内部集合的数据对象,但这些都是相同的对象),它返回了非常好的对象,其中包含我可以轻松访问的所有属性 为了克服序列化程序的限制,我尝试手动反序列化数据: $jsser = New-Object System.Web.Scrip
$jsser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$jsser.MaxJsonLength = $jsser.MaxJsonLength * 10
$jsser.RecursionLimit = 99
$outObject = $jsser.DeserializeObject($json)
该对象看起来不同—内部集合似乎没有反序列化,当我尝试执行属性时,它们返回空结果
我的问题是:
convertfromjson
在序列化之前为对象创建了一个模板。知道如何复制它吗PSCustomObject
;如果我通过Json中的convertfromjson
获取了我想要设置的对象,那么在JsonSerializer中是否仍有将其用作对象类型的方法我把它放在我的代码中:
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
我遇到了同样的问题,并且能够像这样解决它:
[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属性
来源:在结果中使用
调用RestMethod
和大型JSON集合时,我遇到了相同的问题。最后,我修改了中的方法,将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)
}
这些年来,这一条对我很有效:
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
}
是的,但在powershell中,我试图避免导入.Net DLL。powershell有自己的动态对象,动态填充了属性,而且它可以处理2MB以下的文件。我只是想强制它以同样的方式处理2MB以上的文件。我在PowerShell V2.0脚本中使用它。它支持大JSON,但使用起来有点冗长。如果你看看我最初的问题,我已经找到了一种反序列化大JSON的方法。当您自己实例化序列化程序时,可以更改MaxJsonLength属性。您将不得不使用Invoke WebRequest而不是Invoke RestRequest,而不是跟随RawContent查找第一个“{”,并从infront中删除所有内容,这样您就有了一个干净的json。在大型对象上,这种Xml序列化可能会付出代价。感谢您的解决方案。但是,最好替换
return ParseJsonObject($config)
使用返回ParseItem($config)
作为反序列化对象
可能返回数组。为什么将$global:javaScriptSerializer.RecursionLimit
设置为99?默认值为100。节省了我的时间!谢谢:)