【问题标题】:Json circular reference in powershell 2.0 with javascriptSerializer带有javascriptSerializer的powershell 2.0中的Json循环引用
【发布时间】:2017-01-02 20:38:21
【问题描述】:

我正在使用 powershell 2.0 编写脚本,目前无法升级到 3.0 或更高版本。在此脚本中,我尝试使用此链接 (PowerShell 2.0 ConvertFrom-Json and ConvertTo-Json implementation) 中的代码将一些数据序列化为 JSON:

function ConvertTo-Json20([object] $item){
    add-type -assembly system.web.extensions
    $ps_js=new-object system.web.script.serialization.javascriptSerializer
    return $ps_js.Serialize($item)
}

我的问题是我以某种方式获得了循环引用,我真的不知道为什么。我设置了一小段测试数据,结构在 powershell 中看起来像这样:

$testRoot = @{
    "id" = "1"
    "children" = @( 
        @{
            "id" = "2"
            "children" = @( 
                @{
                    "id" = "2";
                };
                @{
                    "id" = "3";
                }
            );
        };
        @{
            "id" = "4"
            "children" = @( 
                @{
                    "id" = "5";
                }
            );
        }
    )
}

我知道它看起来很垃圾,但我只需要这种格式。

我需要序列化的结构有更多的层,所以更多的“孩子”,并且有一点会变得奇怪。

当我尝试这个时:

ConvertTo-Json20 $testRoot

一切正常。结构被解析如下:

{
   "id":"1",
   "children":[
        {
            "id":"2",
            "children":[
               {
                   "id":"2"
               },
               {
                   "id":"3"
               }
            ]
        },
        {
            "id":"4",
            "children":[
               {
                   "id":"5"
               }
            ]
        }
   ]
}

但现在问题来了。如前所述,该结构有更多层,所以我尝试了这个,它只是将数据设置在一个数组中。

ConvertTo-Json20 @($testRoot)

但它不起作用,我只是收到一条错误消息:

Exception in method "Serialize" with 1 argument(s):  
"While serializing an object of type "System.Management.Automation.PSParameterizedProperty" a circular reference was discovered."
At C:\Users\a38732\Desktop\Temp.ps1:34 symbol:28
+     return $ps_js.Serialize <<<< ($item)
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

(我把错误信息从德语翻译过来,所以英文版可能会有一些不同的词...)

【问题讨论】:

  • 我刚刚在另一台机器上使用 Powershell 4.0 进行了尝试,它与内置的 json 序列化程序一起使用。 ConvertTo-Json @($testRoot)
  • 有人知道如何调整 javascriptSerializer 来对其进行序列化吗?该文档没有多大帮助...
  • 您的示例格式错误。数组中的条目用逗号分隔,而不是分号。该函数也不需要数组,它需要一个[object]
  • @TheIncorrigible1 - 同意数组元素通常用逗号分隔,但实际上是@( )array subexpression operator is special。引用:“将一个或多个语句的结果作为数组返回。”例如@(Get-Date; Start-Sleep -s 1; Get-Date)。由于arrayobject,因此该函数完全有效。一个问题是 JavaScriptSerializer.Serialize() 除了 simple JSON 之外的任何东西都无用。
  • 如果只是序列化一个(复杂的)对象以供同一系统重用或与另一个 PowerShell 系统交换,您可能会考虑ConvertTo-Expression cmdlet from the PowerShell Gallery 向下兼容 PSv2.0。可以使用Invoke-Expression 或仅使用与号 (&amp;) 或 dot sourcing 包含结果的.ps1 文件轻松调用(反序列化)结果。

标签: json powershell powershell-2.0 javascriptserializer


【解决方案1】:

一个问题是JavaScriptSerializer 类本身的使用。截至此日期,documentation itself concedes it should not be used to serialize nor deserialize JSON。引用:

Json.NET应该用于序列化和反序列化。

如果您能够使用像 Json.NET 这样的第三方库,那么这里有一个简单的函数,可以根据 OP 中的数据结构来满足您的需求:

function ConvertTo-JsonNet {
   [CmdletBinding()]
    param(
        [Parameter(Mandatory)] $object,
        [Parameter(Mandatory)] [string]$jsonNetPath,
        [switch]$indent,
        [switch]$preserveReferencesHandling
    )
    Add-Type -Path $jsonNetPath;

    $formatting = if ($indent.IsPresent) { [Newtonsoft.Json.Formatting]::Indented; }
    else { [Newtonsoft.Json.Formatting]::None; }

    $settings = New-Object Newtonsoft.Json.JsonSerializerSettings;
    if ($preserveReferencesHandling.IsPresent) { 
        $settings.PreserveReferencesHandling = [Newtonsoft.Json.PreserveReferencesHandling]::Objects;
    }

    [Newtonsoft.Json.JsonConvert]::SerializeObject($object, $formatting, $settings);
}

简单用法,假设Newtonsoft.Json.dll 与您的脚本在同一目录中:

$dllPath = Join-Path $PSScriptRoot 'Newtonsoft.Json.dll';
ConvertTo-JsonNet @($testRoot) $dllPath;

输出:

[{"id":"1","children":[{"id":"2","children":[{"id":"2"},{"id":"3"}]},{"id":"4","children":[{"id":"5"}]}]}]

您可以从nuget package project site 手动下载 .dll。它有一个.nupkg 文件扩展名,但它是一个压缩存档,所以将扩展名重命名为.zip 就可以了。在lib 子目录中,有适用于 .NET 2.0 到 4.5 版本的 .dll 文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 2014-04-14
    • 2021-06-10
    • 1970-01-01
    • 2018-11-23
    • 2015-10-27
    相关资源
    最近更新 更多