Unexpected ConvertTo-Json results? Answer: it has a default -Depth of 2

一曲冷凌霜 提交于 2019-11-26 19:11:41

Answer

ConvertTo-Json has a -Depth parameter:

Specifies how many levels of contained objects are included in the JSON representation.
The default value is 2.

Example

To do a full round-trip with a JSON file you need to increase the -Depth for the ConvertTo-Json cmdlet:

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

TL;DR

Probably because ConvertTo-Json terminates branches that are deeper than the default -Depth (2) with a (.Net) full type name, programmers assume a bug or a cmdlet limitation and do not read the help or about.
Personally, I think a string with a simple ellipsis (three dots: …) at the end of the cut off branch, would have a clearer meaning (see also: Github issue: 8381)

Why?

This issue often ends up in another discussion as well: Why is the depth limited at all?

Some objects have circular references, meaning that a child object could refer to a parent (or one of its grandparents) causing a infinitive loop if it would be serialized to JSON.

Take for example the following hash table with a parent property that refers to the object itself:

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

If you execute: $Test | ConvertTo-Json it will conveniently stop at a depth level of 2 by default:

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

This is why it is not a good idea to automatically set the -Depth to a large amount.

Your question clearly illustrates how much of a pain point the current default ConvertTo-Json behavior is.

As for the justification of the behavior:

Some objects have circular references

Internally, ConvertTo-Json actually has a safety feature that prevents infinitely deep serialization: it reports an error if the depth exceeds 100 levels.

This internal limit should be enough.

While -Depth can be useful to intentionally truncate an input object tree whose full depth you don't need,
-Depth defaulting to 2 and quietly truncating the output amounts to quiet de-facto failure of the serialization from the unsuspecting user's perspective - failure that may not be discovered until later.

The seemingly arbitrary and quiet truncation is surprising to most users, and having to account for it in every ConvertTo-Json call is an unnecessary burden.

I've created this GitHub issue to request changing the current behavior, specifically as follows:

  • Remove the default value for -Depth

    • The hard-coded internal limit of 100, which when exceeded, reports an error, is sufficient to prevent "runaway" JSON strings stemming from object tress with cyclic dependencies.
    • Typical input objects will then be fully serialized by default, which is typically the intent.
  • Use -Depth solely at the user's discretion in order to:

    • Intentionally truncate the input object tree at the specified depth.
    • On rare occasions, allow serialization of object trees that are deeper than 100 levels.

Make your voice heard there, if you'd like to see this change happen (or disagree).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!