web-dev-qa-db-fra.com

Résultats ConvertTo-Json inattendus? Réponse: il a une profondeur par défaut de 2

Pourquoi est-ce que je deviens inattendu ConvertTo-Json résultats, pourquoi obtenir des valeurs comme System.Collections.Hashtable et/ou pourquoi un aller-retour ($Json | ConvertFrom-Json | ConvertTo-Json) échouer?

Problème de méta

Stackoverflow a un bon mécanisme pour éviter les questions en double mais pour autant que je puisse voir, il n'y a pas de mécanisme pour empêcher les questions qui ont un double cause . Prenons cette question comme exemple: presque chaque semaine, une nouvelle question arrive avec la même cause, mais il est souvent difficile de la définir comme un doublon car la question elle-même est juste légèrement différente. Néanmoins, je ne serais pas surpris si cette question/réponse elle-même finit en double (ou hors sujet) mais malheureusement, stackoverflow n'a pas la possibilité de écrire un article pour empêcher d'autres programmeurs de continuer à écrire des questions causée par cet écueil "connu".

Doublons

Quelques exemples de questions similaires avec la même cause commune:

Différent

Alors, est-ce que cette question "auto-répondue" diffère des doublons ci-dessus?
.

11
iRon

Répondre

ConvertTo-Json a un -Depth paramètre:

Spécifie combien de niveaux d'objets contenus sont inclus dans la représentation JSON.
La valeur par défaut est 2 .

Exemple

Pour effectuer un aller-retour complet avec un fichier JSON, vous devez augmenter le -Depth pour le ConvertTo-Json applet de commande:

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

TL; DR

Probablement parce que ConvertTo-Json termine les branches plus profondes que la valeur par défaut -Depth ( 2 ) avec un nom de type complet (.Net), les programmeurs supposent un bogue ou une limitation d'applet de commande et ne lisent pas l'aide ou à propos.
Personnellement, je pense qu'une chaîne avec un simple Ellipsis (trois points:…) à la fin de la branche coupée, aurait un sens plus clair (voir aussi: Problème Github: - 8381 )

Pourquoi?

Ce problème se retrouve souvent dans une autre discussion également: Pourquoi la profondeur est-elle limitée?

Certains objets ont des références circulaires, ce qui signifie qu'un objet enfant pourrait faire référence à un parent (ou l'un de ses grands-parents) provoquant une boucle infinitive s'il était sérialisé en JSON.

Prenons par exemple la table de hachage suivante avec une propriété parent qui fait référence à l'objet lui-même:

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

Si vous exécutez: $Test | ConvertTo-Json il s'arrêtera commodément à un niveau de profondeur de 2 par défaut:

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

C'est pourquoi ce n'est pas une bonne idée de définir automatiquement le -Depth à un montant élevé.

6
iRon

Vos questions et réponses utiles illustrent clairement à quel point la douleur est la valeur par défaut actuelle ConvertTo-Json le comportement est.

Quant à la justification du comportement:

Tandis que -Depth peut être utile pour intentionnellement tronquer une arborescence d'objets d'entrée dont vous n'avez pas besoin de toute la profondeur,
-Depth par défaut à 2 et troncature silencieuse la sortie équivaut à échec de facto silencieux de la sérialisation du point de vue de l'utilisateur sans méfiance - échec qui ne pourra être découvert que plus tard.

La troncature apparemment arbitraire et silencieuse surprend la plupart des utilisateurs et doit en tenir compte dans chaque ConvertTo-Json l'appel est une charge inutile.

J'ai créé ce problème GitHub pour demander de changer le comportement actuel, en particulier comme suit:

  • Ignorer -Depth pour [pscustomobject] graphes d'objets (une hiérarchie de ce qui est conceptuellement des DTO (objets de transfert de données, "sacs de propriétés"), tels que renvoyés par Convert*From*-Json), en particulier.

    • Il le fait est logique d'avoir une limite de profondeur automatique pour types .NET arbitraires, car ils peuvent être des graphiques d'objets de profondeurs excessives et peuvent même contenir des références circulaires; par exemple., Get-ChildItem | ConvertTo-Json peut devenir rapidement incontrôlable, avec -Depth valeurs aussi basses que 4.

    • Notez que les collections imbriquées, y compris les tables de hachage, ne sont pas elles-mêmes soumises à la limite de profondeur uniquement leurs (scalaires) éléments.

    • Cette distinction entre les DTO et les autres types est en fait utilisée par PowerShell lui-même dans les coulisses, à savoir dans le contexte de la sérialisation pour à distance et emplois d'arrière-plan.

  • Utilisation de -Depth n'est alors nécessaire que pour intentionnellement tronquer l'arborescence des objets d'entrée à la profondeur spécifiée ou sérialiser à un niveau plus profond (si nécessaire si à une profondeur supérieure à la limite de profondeur maximale interne, 100)

Faites entendre votre voix , si vous souhaitez voir ce changement se produire (ou en désaccord).

2
mklement0