我有
function Foo($a, $b)
{
$o = @{}
$o.A = $a
$o.B = $b
$post = @{}
$post.X="x"
$post.entity =$o
$newton::SerializeObject($post)
}
然后做
foo "a" "b"
我得到了
Exception calling "SerializeObject" with "1" argument(s): "Self referencing loop detected for property 'Value' with type 'System.Management.Automation.PSParameterizedProperty'. Path 'entity.Members[0]'."
然而
function Foo2($o)
{
$post = @{}
$post.X="x"
$post.entity =$o
$newton::SerializeObject($post)
}
foo2 @{a="a"; b="b"}
工作正常。还
function foo3($a, $b)
{
$o = @{}
$o.A = $a
$o.B = $b
$newton::SerializeObject($o)
}
foo3 "a" "b"
有效但
foo3 "a" 1
失败
后者可以通过
来实现 $o.B= [Int32]::Parse($b.Tostring())
这一切似乎很奇怪
Windows 7上的powershell v2,json.net 4.4.5
答案 0 :(得分:9)
.NET框架中的JavaScriptSerializer
在序列化PowerShell的哈希时也存在类似的问题。我怀疑它在PowerShell类型系统中有些奇怪。你可以完全跳过Json.Net并推出自己的。
以下是启动你的事情。它可能不如PowerShell 3的内置ConvertTo-Json
cmdlet强大,但我认为它基本上是完整的。
以下是所有您的示例,处于正常工作状态。
# See below for ConvertTo-Json.psm1
Import-Module ConvertTo-Json
function Foo($a, $b)
{
$o = @{}
$o.A = $a
$o.B = $b
$post = @{}
$post.X="x"
$post.entity =$o
ConvertTo-Json $post
}
function Foo2($o)
{
$post = @{}
$post.X="x"
$post.entity =$o
ConvertTo-Json $post
}
function foo3($a, $b)
{
$o = @{}
$o.A = $a
$o.B = $b
ConvertTo-Json $o
}
PS> foo "a" "b"
{"entity":{"A":"a","B":"b"},"X":"x"}
PS> foo2 @{a="a"; b="b"}
{"entity":{"a":"a","b":"b"},"X":"x"}
PS> foo3 "a" "b"
{"A":"a","B":"b"}
PS> foo3 "a" 1
{"A":"a","B":1}
这是实现ConvertTo-Json
的PowerShell模块。
# Save these contents to Modules\ConvertTo-Json\ConvertTo-Json.psm1 in your
# PowerShell documents folder, and load them in your $profile using the
# "Import-Module ConvertTo-Json" cmdlet. This will make the ConvertTo-Json cmdlet
# available for use.
Set-StrictMode -Version Latest
function convertToJsonNull($InputObject) {
"null"
}
function convertToJsonArray($InputObject) {
$value = ($InputObject | %{ convertToJson $_ }) -join ','
"[$value]"
}
function convertToJsonHash($InputObject) {
$value = ($InputObject.Keys | %{
$name = $_ | asJsonString
$itemValue = convertToJson ($InputObject[$_])
'"{0}":{1}' -f $name, $itemValue
}) -join ','
"{$value}"
}
function convertToJsonObject($InputObject) {
$value = ($InputObject | get-member -membertype *property | %{
$name = $_.Name
$value = convertToJson ($InputObject.($name))
'"{0}":{1}' -f ($name | asJsonString), $value
}) -join ','
"{$value}"
}
function convertToJsonString($InputObject) {
'"{0}"' -f ($InputObject | asJsonString)
}
function convertToJsonBool($InputObject) {
$InputObject.ToString().ToLower()
}
function convertToJsonNumeric($InputObject) {
"$InputObject"
}
function convertToJsonDate($InputObject) {
$epoch = [datetime]"1970-01-01T00:00:00Z"
$elapsed = [long]($InputObject - $epoch).TotalMilliseconds
'"\/Date({0})\/"' -f $elapsed
}
filter isNumeric() {
$_ -is [byte] -or $_ -is [int16] -or $_ -is [int32] -or $_ -is [int64] -or
$_ -is [sbyte] -or $_ -is [uint16] -or $_ -is [uint32] -or $_ -is [uint64] -or
$_ -is [float] -or $_ -is [double] -or $_ -is [decimal]
}
filter asJsonString {
($_ -replace '\\', '\\') -replace '"', '\"'
}
function convertToJson($InputObject) {
if ($InputObject -eq $null) { convertToJsonNull $InputObject }
elseif ($InputObject -is [array]) { convertToJsonArray $InputObject }
elseif ($InputObject -is [hashtable]) { convertToJsonHash $InputObject }
elseif ($InputObject -is [datetime]) { convertToJsonDate $InputObject }
elseif ($InputObject -is [string]) { convertToJsonString $InputObject }
elseif ($InputObject -is [char]) { convertToJsonString $InputObject }
elseif ($InputObject -is [bool]) { convertToJsonBool $InputObject }
elseif ($InputObject | isNumeric) { convertToJsonNumeric $InputObject }
else { convertToJsonObject $InputObject }
}
function ConvertTo-Json {
[CmdletBinding()]
param(
[Parameter(
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
$InputObject
)
convertToJson $InputObject
}
Export-ModuleMember -Function ConvertTo-Json
答案 1 :(得分:2)
自我引用循环问题完全是......分配事物的顺序。以下示例有效:
function Foo($a, $b)
{
$o = @{}
$post = @{}
$post.entity =$o
$o.A = $a
$o.B = $b
$post.X="x"
[Newtonsoft.Json.JsonConvert]::SerializeObject($post)
}
Foo "a" "b"
{"entity":{"A":"a","B":"b"},"X":"x"}
如果在传递之前转换类型,那么它将使你的foo3函数保持通用:
function foo3($a, $b)
{
$o = @{}
$o.A = $a
$o.B = $b
[Newtonsoft.Json.JsonConvert]::SerializeObject($o)
}
$var2 = [Int32]::Parse((1).Tostring())
Foo3 "a" $var2
{"A":"a","B":1}