web-dev-qa-db-ja.com

予期しないConvertTo-Jsonの結果?回答:デフォルトの深さは2です。

なぜ予期しない結果になるのですか ConvertTo-Json 結果、なぜSystem.Collections.Hashtableおよび/または往復($Json | ConvertFrom-Json | ConvertTo-Json) 不合格?

メタ問題

Stackoverflowは重複questionsを防止するための優れたメカニズムを備えていますが、私が見る限り、重複原因。この質問を例に取ってみましょう。ほぼ毎週新しい質問が同じ原因で発生しますが、質問自体がわずかに異なるだけなので、それを重複として定義することはしばしば困難です。それでも、この質問/回答自体が重複(またはトピック外)になったとしても驚くことはありませんが、残念ながら、stackoverflowで 記事を書く が他のプログラマーが質問を書き続けるのを防ぐことができません。この「既知の」落とし穴が原因です。

重複

同じ一般的な原因を持つ同様の質問のいくつかの例:

違う

では、この「自己回答」の質問は上記の重複とは違うのでしょうか。
タイトルには共通の原因があり、同じ原因による質問の繰り返しを防ぐ方がよい場合があります。

11
iRon

回答

ConvertTo-Json には-Depthパラメータがあります:

JSON表現に含まれるオブジェクトのレベル数を指定します。
default の値は 2 です。

JSONファイルで完全なラウンドトリップを行うには、-DepthコマンドレットのConvertTo-Jsonを増やす必要があります。

$Json | ConvertFrom-Json | ConvertTo-Json -Depth 9

TL; DR

おそらくConvertTo-Jsonは、デフォルトの-Depth 2 )より深いブランチを(.Net)完全型名で終了するため、プログラマはバグまたはコマンドレットの制限。ヘルプなどについては読みません。
個人的には、カットオフブランチの末尾に単純な Ellipsis (3つのドット:…)が付いた文字列は、より明確な意味を持つと思います(Githubの問題も参照:- 8381

どうして?

この問題は多くの場合、別のディスカッションでも終わります:なぜ深さが制限されているのですか?

一部のオブジェクトには循環参照があります。つまり、子オブジェクトが親(またはその祖父母の1つ)を参照する可能性があり、JSONにシリアル化すると無限ループが発生します。

たとえば、オブジェクト自体を参照するparentプロパティを持つ次のハッシュテーブルを考えてみます。

$Test = @{Guid = New-Guid}
$Test.Parent = $Test

次を実行すると、$Test | ConvertTo-Jsonはデフォルトで深度レベル2で停止します。

{
    "Guid":  "a274d017-5188-4d91-b960-023c06159dcc",
    "Parent":  {
                   "Guid":  "a274d017-5188-4d91-b960-023c06159dcc",
                   "Parent":  {
                                  "Guid":  "a274d017-5188-4d91-b960-023c06159dcc",
                                  "Parent":  "System.Collections.Hashtable"
                              }
               }
}

このため、-Depthを自動的に大量に設定することはお勧めできません。

6
iRon

役立つ質問と回答は、現在のデフォルトのConvertTo-Jsonの動作がどれほど問題になるかを明確に示しています。

動作の justification について:

-Depthは、意図的に必要のない完全な深さの入力オブジェクトツリーを切り捨てるのに役立ちますが、
-Depth defaulting to 2 and quietly truncating 出力量は疑いを持たないユーザーの観点からのシリアル化の静かな事実上の失敗-後でないと発見できない可能性のある失敗。

ほとんどのユーザーにとって一見恣意的で静かな切り捨ては驚くべきことであり、すべてのConvertTo-Json呼び出しでそれを考慮する必要があることは不必要な負担です。

私は このGitHubの問題 を作成して、具体的には次のように現在の動作の変更を要求します。

  • 特に、-Depthから返された[pscustomobject]オブジェクトグラフ(概念的にはDTO(データ転送オブジェクト、「プロパティバッグ」)の階層)のConvert*From*-Jsonを無視します。

    • does arbitrary .NET types 、深すぎるオブジェクトグラフである可能性があり、循環参照が含まれる場合さえある。たとえば、Get-ChildItem | ConvertTo-Jsonの値は-Depthと同じくらい低いため、4はすぐに手に負えなくなります。

    • ネストされた collections (ハッシュテーブルを含む)自体は、(スカラー) elements のみの深さ制限の対象ではないことに注意してください。

    • DTOと他のタイプのこの区別は、実際にはPowerShell自体の裏側で使用されています、つまり remoting のシリアル化のコンテキストでおよび background jobs

  • 次に、-Depthの使用は、意図的に入力オブジェクトツリーを指定された深度で切り捨てるか、より深いレベルにシリアル化するためにのみ必要です(内部の最大深度の制限よりも深い場合は、 100

あなたの声を聞かせてください there 、この変化が起こるのを見たい(または同意しない)場合。

2
mklement0