7

私は持っている

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

4

2 に答える 2

9

.NET フレームワークのJavaScriptSerializerにも、PowerShell のハッシュをシリアル化する際に同様の問題があります。私は、PowerShell 型システムで少し奇妙なことを疑っています。Json.Net を完全にスキップして、独自のロールを作成できます。

以下は、あなたを始めるためのものです。PowerShell 3 の組み込みConvertTo-Jsonコマンドレットほど堅牢ではない可能性がありますが、ほぼ完成していると思います。

これがすべての例です。

# 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}

を実装する PowerShell モジュールは次のとおりですConvertTo-Json

# 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
于 2012-06-07T08:19:39.650 に答える
3

自己参照ループの問題は、すべてについてのようです....物事を割り当てる順序。以下の例は動作します:

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}
于 2012-06-07T15:23:07.790 に答える