Неожиданные результаты ConvertTo-Json? Ответ: по умолчанию - Глубина 2
Почему я получаю неожиданное ConvertTo-Json
Результаты?
Мета выпуск
В Stackru есть хороший механизм предотвращения повторяющихся вопросов, но, насколько я вижу, нет механизма предотвращения повторяющихся вопросов. Возьмите этот вопрос в качестве примера: почти каждую неделю появляется новый вопрос с одной и той же причиной, но зачастую трудно определить его как дубликат, потому что сам вопрос немного отличается. Тем не менее, я не удивлюсь, если сам этот вопрос / ответ окажется дубликатом (или не по теме), но, к сожалению, stackru не имеет возможности написать статью, чтобы помешать другим программистам продолжать писать вопросы, вызванные этой "известной" ошибкой,
Дубликаты
Несколько примеров похожих вопросов с той же общей причиной:
- PowerShell ConvertTo-Json не конвертирует массив, как ожидалось (вчера)
- Powershell ConvertTo-json со встроенной хэш-таблицей
- PowerShell "ConvertTo-Json" испортил вывод в формате JSON
- Вложенные массивы и ConvertTo-Json
- В Powershell ConvertTo-JSON отсутствует вложенный уровень
- Как сохранить объект JSON в файл с помощью Powershell?
- Не удается правильно преобразовать PSCustomObjects в массиве обратно в JSON
- ConvertTo-Json выравнивает массивы более чем на 3 уровня
- Добавить массив объектов в PSObject сразу
- Почему ConvertTo-Json сбрасывает значения
- ...
Разные
Так чем же этот вопрос с "самоотвечением" отличается от приведенных выше дубликатов?
У него есть общая причина в названии, и это может лучше предотвратить повторение вопросов по той же причине.
3 ответа
Ответ
ConvertTo-Json
имеет -Depth
параметр:
Указывает, сколько уровней содержащихся объектов включено в представление JSON.
Значением по умолчанию является 2.
TL; DR
Наверное потому что ConvertTo-Json
завершает ветви, которые глубже, чем по умолчанию -Depth
(2) с полным именем типа (.Net) программисты принимают ошибку или ограничение командлета и не читают справку или информацию о ней.
Лично я думаю, что строка с простым многоточием (три точки: …) в конце обрезанной ветви будет иметь более ясное значение (см. Также: выпуск Github: 8381)
Зачем?
Этот вопрос часто заканчивается и другим обсуждением: почему глубина вообще ограничена?
Некоторые объекты имеют циклические ссылки, что означает, что дочерний объект может ссылаться на родителя (или одного из его дедушек и бабушек), вызывая бесконечный цикл, если он будет сериализован в 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
в большом количестве.
Ваш вопрос ясно показывает, насколько болевые точки соответствуют текущим значениям по умолчанию. ConvertTo-Json
поведение есть.
Что касается обоснования поведения:
Некоторые объекты имеют циклические ссылки
Внутренне ConvertTo-Json
на самом деле имеет функцию безопасности, которая предотвращает бесконечно глубокую сериализацию: она сообщает об ошибке, если глубина превышает 100
уровни.
Этого внутреннего предела должно быть достаточно.
В то время как -Depth
может быть полезным для преднамеренного усечения дерева входных объектов, полная глубина которого вам не нужна, -Depth
по умолчанию 2
и тихое усечение вывода означает тихий фактический сбой сериализации с точки зрения ничего не подозревающего пользователя - сбой, который может быть обнаружен только позже.
Казалось бы, произвольное и тихое усечение удивляет большинство пользователей, и приходится учитывать его в каждом ConvertTo-Json
Звонить - это ненужное бремя.
Я создал эту проблему GitHub, чтобы запросить изменение текущего поведения, а именно:
Удалить значение по умолчанию для
-Depth
- Жестко закодированный внутренний предел
100
При превышении которого выдается сообщение об ошибке, этого достаточно, чтобы предотвратить "убегающие" строки JSON, возникающие из-за тресса объекта с циклическими зависимостями. - Типичные входные объекты будут полностью сериализованы по умолчанию, что обычно является намерением.
- Жестко закодированный внутренний предел
использование
-Depth
исключительно по усмотрению пользователя для того, чтобы:- Умышленное усечение дерева входных объектов на заданной глубине.
- В редких случаях разрешите сериализацию деревьев объектов, которые глубже, чем
100
уровни.
Сделайте так, чтобы ваш голос был услышан там, если вы хотите, чтобы это изменение произошло (или не согласилось).
.. | ConvertTo-Json -Depth 100 | ..
Максимальная глубина — 100 в последней версии PowerShell (моя: 7.3.4, переименована в PowerShell Core).