Неожиданные результаты ConvertTo-Json?Ответ: по умолчанию - Глубина 2 - PullRequest
0 голосов
/ 02 декабря 2018

Почему я получаю неожиданные ConvertTo-Json результаты?
И почему происходит сбой в оба конца ($Json | ConvertFrom-Json | ConvertTo-Json)?

Мета-проблема

В Stackoverflow есть хороший механизм предотвращения дублирования вопросов , но, насколько я вижу, не существует механизма предотвращения дублирования вопросов , вызывающих .Возьмите этот вопрос в качестве примера: почти каждую неделю появляется новый вопрос с одной и той же причиной, но зачастую трудно определить его как дубликат, потому что сам вопрос немного отличается.Тем не менее, я не удивлюсь, если сам этот вопрос / ответ окажется дубликатом (или не по теме), но, к сожалению, stackoverflow не имеет возможности написать статью , чтобы помешать другим программистам продолжать писать вопросы, вызванныеэтой «известной» ошибкой.

Дубликаты

Несколько примеров похожих вопросов по той же общей причине:

Разное

Итак, были лиэтот вопрос с «самостоятельным ответом» отличается от вышеупомянутых дубликатов?
У него есть общая причина в названии, и поэтому он может лучше предотвратить повторение вопросов по той же причине.

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Ваш вопрос ясно иллюстрирует, насколько болезненной является текущее поведение по умолчанию ConvertTo-Json.

Что касается оправдания поведения:

Некоторые объекты имеют циклические ссылки

Внутренне, ConvertTo-Json на самом деле имеет функцию безопасности, которая предотвращает бесконечно глубокую сериализацию: она сообщает об ошибке , если глубина превышает уровни 100.

Этого внутреннего предела должно быть достаточно.

Хотя -Depth может быть полезным для преднамеренного усечения дерева входных объектов, полная глубина которого вам не нужна,
-Depth по умолчанию до 2 и тихое усечение выход составляет тихий фактический сбой сериализации с точки зрения ничего не подозревающего пользователя - сбой, который может быть обнаружен только позже.

Казалось бы, произвольное и тихое усечение удивляет большинство пользователей, и необходимость учитывать его при каждом вызове ConvertTo-Json являетсяненужное бремя.

Я создал эту проблему GitHub , чтобы запросить изменение текущего поведения, а именно:

  • Удалитезначение по умолчанию для -Depth

    • Жестко запрограммированный внутренний предел 100, который при превышении сообщает об ошибке, достаточен для предотвращения «убегающих» строк JSON, происходящих из тресса объекта с циклическими зависимостями.
    • Типичные входные объекты будут полностью сериализованы по умолчанию, что обычно является намерением.
  • Используйте -Depth исключительно по усмотрению пользователя, чтобы:

    • Намеренно обрезать дерево входных объектов вуказанная глубина.
    • В редких случаях разрешите сериализацию деревьев объектов глубже, чем 100 уровней.

Сделайте так, чтобы ваш голос был услышан там, еслиВы хотели бы, чтобы это изменение произошло (или не было).

0 голосов
/ 02 декабря 2018

Ответ

ConvertTo-Json имеет параметр -Depth:

Указывает, сколько уровней содержащихся объектов включенов представлении JSON.
Значение по умолчанию равно 2 .

Пример

Для выполнения полного обхода сJSON-файл, который нужно увеличить -Depth для командлета ConvertTo-Json:

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

TL; DR

Возможно, потому что ConvertTo-Json завершает ветви, которые глубже, чем по умолчанию -Depth ( 2 ) с полным именем типа (.Net), программисты предполагают ошибку или ограничение командлета и не читают справку или информацию.
Лично я считаю строку с простым многоточие (три точки:…) в конце обрезанной ветви будет иметь более ясное значение (см. Также: выпуск Github: 8381 )

Почему?

Эта проблема часто заканчивается в другом обсуждении: Почему глубина вообще ограничена?

В некоторых объектах есть циркулирующиеr указывает, что дочерний объект может ссылаться на родителя (или одного из его дедушек и бабушек), вызывая бесконечный цикл, если он будет сериализован в 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 на большое количество.

...