PowerShell v2 从函数返回时将字典转换为数组
PowerShell v2 Converts Dictionary to Array when returned from a function
首先,我绑定到 PowerShell v2,因为这是 Windows 7 上默认安装的。我想做的事情开箱即用 PowerShell v4,可能还有 PowerShell v3 .
我想从文件中读取 JSON 对象并将其用作脚本中的对象。 PowerShell v2 没有 ConvertFrom-Json 方法,因此我编写了自己的实现,希望具有相同的功能:
function ConvertFrom-Json
{
param(
[Parameter(ValueFromPipeline=$true)]
[string]$json
)
[System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$ser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$obj = $ser.DeserializeObject($json)
Write-Host $obj.GetType()
return $obj
}
我这样调用这个函数:
$configObj = (Get-Content $configFile) -join "`n" | ConvertFrom-Json
Write-Host $configObj.GetType()
这个输出:
System.Collections.Generic.Dictionary`2[System.String,System.Object]
System.Object[]
而且我无法像对象一样与 $configObj 交互并获取它的属性。事实上,我不知道如何从中获取任何信息。当我打印对象时,输出如下所示:
AC Version Location
--- ------- --------
True v2.0.50727 C:\Windows\assembly\GAC_MSIL\System.Web.Extensions.5.0.0__31bf3856ad364e35\System.Web.Extensions.dll
Key : DownloadURL
Value : https://example.com
Key : dir
Value :
当我希望它看起来像:
Key Value
--- -----
DownloadURL https://example.com
dir
有没有办法解决这个问题并从我的 ConvertFrom-Json 方法中获取与我的方法中存在的对象相同的对象?
提前致谢,
安迪
除赋值和 increment/decrement 外,每个语句的结果都被视为函数的一部分 return。您不必使用 return
语句来 return 函数中的某些内容。所以你的函数实际上 return 两个对象:从 LoadWithPartialName
方法加载 Assembly
对象和从 $obj
变量加载字典。当您将多个函数结果分配给变量时,PowerShell 必须将结果打包到数组中。由于您实际上并不需要 Assembly
对象,因此可以将 LoadWithPartialName
方法的结果转换为 [void]
:
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
另外 LoadWithPartialName
方法是 Obsolete
,您根本不应该使用它。要加载程序集,您可以使用 Add-Type
内置 cmdlet:
Add-Type -AssemblyName System.Web.Extensions
由于您不在函数中使用命名块,因此所有代码都被视为 end
块,因此您只处理函数中的最后一个管道输入。您应该使用 process
块来处理每个管道输入对象:
process{
$ser.DeserializeObject($json)
}
当语句 return 集合时,PowerShell 会枚举此集合并将每个单独的集合的项目而不是集合作为单个元素写入。因此,如果您的 JSON 在顶层包含数组,您的函数将 return 数组元素而不是数组本身,就像内置 ConvertFrom-Json
那样。您可以使用一元数组运算符来防止枚举 returned 数组:
,$ser.DeserializeObject($json)
总数:
function ConvertFrom-Json {
param(
[Parameter(ValueFromPipeline=$true)]
[string]$json
)
begin {
Add-Type -AssemblyName System.Web.Extensions
$ser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
}
process {
,$ser.DeserializeObject($json)
}
}
首先,我绑定到 PowerShell v2,因为这是 Windows 7 上默认安装的。我想做的事情开箱即用 PowerShell v4,可能还有 PowerShell v3 .
我想从文件中读取 JSON 对象并将其用作脚本中的对象。 PowerShell v2 没有 ConvertFrom-Json 方法,因此我编写了自己的实现,希望具有相同的功能:
function ConvertFrom-Json
{
param(
[Parameter(ValueFromPipeline=$true)]
[string]$json
)
[System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
$ser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$obj = $ser.DeserializeObject($json)
Write-Host $obj.GetType()
return $obj
}
我这样调用这个函数:
$configObj = (Get-Content $configFile) -join "`n" | ConvertFrom-Json
Write-Host $configObj.GetType()
这个输出:
System.Collections.Generic.Dictionary`2[System.String,System.Object]
System.Object[]
而且我无法像对象一样与 $configObj 交互并获取它的属性。事实上,我不知道如何从中获取任何信息。当我打印对象时,输出如下所示:
AC Version Location
--- ------- --------
True v2.0.50727 C:\Windows\assembly\GAC_MSIL\System.Web.Extensions.5.0.0__31bf3856ad364e35\System.Web.Extensions.dll
Key : DownloadURL
Value : https://example.com
Key : dir
Value :
当我希望它看起来像:
Key Value
--- -----
DownloadURL https://example.com
dir
有没有办法解决这个问题并从我的 ConvertFrom-Json 方法中获取与我的方法中存在的对象相同的对象?
提前致谢,
安迪
除赋值和 increment/decrement 外,每个语句的结果都被视为函数的一部分 return。您不必使用 return
语句来 return 函数中的某些内容。所以你的函数实际上 return 两个对象:从 LoadWithPartialName
方法加载 Assembly
对象和从 $obj
变量加载字典。当您将多个函数结果分配给变量时,PowerShell 必须将结果打包到数组中。由于您实际上并不需要 Assembly
对象,因此可以将 LoadWithPartialName
方法的结果转换为 [void]
:
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
另外 LoadWithPartialName
方法是 Obsolete
,您根本不应该使用它。要加载程序集,您可以使用 Add-Type
内置 cmdlet:
Add-Type -AssemblyName System.Web.Extensions
由于您不在函数中使用命名块,因此所有代码都被视为 end
块,因此您只处理函数中的最后一个管道输入。您应该使用 process
块来处理每个管道输入对象:
process{
$ser.DeserializeObject($json)
}
当语句 return 集合时,PowerShell 会枚举此集合并将每个单独的集合的项目而不是集合作为单个元素写入。因此,如果您的 JSON 在顶层包含数组,您的函数将 return 数组元素而不是数组本身,就像内置 ConvertFrom-Json
那样。您可以使用一元数组运算符来防止枚举 returned 数组:
,$ser.DeserializeObject($json)
总数:
function ConvertFrom-Json {
param(
[Parameter(ValueFromPipeline=$true)]
[string]$json
)
begin {
Add-Type -AssemblyName System.Web.Extensions
$ser = New-Object System.Web.Script.Serialization.JavaScriptSerializer
}
process {
,$ser.DeserializeObject($json)
}
}