2012-05-24 2 views
7

У меня естьстранность использованием newtonsoft json.net с PowerShell

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()) 

Что все это кажется очень странным

PowerShell v2 на окно s 7, json.net 4.4.5

+1

Это интересный набор наблюдений, но я не уверен, каков ваш вопрос. Чего вы пытаетесь достичь? –

+0

Я почти уверен, что мой ответ на самом деле разрешил вашу проблему, не требуя изменений в библиотеке/и т. Д. Но я не видел комментариев по моему ответу и ни одного задания на мой ответ. – Peter

ответ

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} 
+0

Я действительно хотел объяснить, что происходит, у меня уже есть работа, но все равно – pm100

9

JavaScriptSerializer из .NET framework также имеет аналогичную проблему с сериализацией хешей PowerShell. Я подозреваю, что это немного странно в системе типа PowerShell. Вы можете вообще пропустить Json.Net и бросить свой собственный.

Ниже вы можете начать с вас. Скорее всего, это не так надежно, как встроенный командлет ConvertTo-Json PowerShell 3, но я думаю, что он в основном завершен.

всего ваших примеров в рабочем состоянии.

# 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 
+0

обратите внимание на случай, когда я назначаю переменную, значение которой равно 1, и это не удается, но если я преобразую ее в строку и затем преобразую ее обратно в int, она отлично работает. Здесь нет хешей – pm100

+0

@ pm100 Да, я это видел. Вы по-прежнему присваиваете преобразованное вручную значение '$ o.B', а' $ o' действительно хеш. Мое решение позволит вам сделать это, не требуя, чтобы вызывающий выполнял ручную проверку любых значений, необходимых для преобразования, или создания исходного объекта каким-либо определенным образом. –

+0

@ pm100 Я просто добавил поддержку объектов и PSObjects, поэтому вам больше не нужно использовать хеши, если вы этого не хотите. –

Смежные вопросы