HJSON C# библиотека для Powershell

Я пытаюсь использовать библиотеку HJSON C# для Powershell: https://github.com/hjson/hjson-cs Я успешно скомпилировал dll, поместил его в папку и добавил тип с помощью стандартной процедуры:

#LOAD
$scriptRoot = Split-Path $script:psEditor.GetEditorContext().CurrentFile.Path

$FilePath = ( Get-Item .\Hjson.dll ).FullName
[System.Reflection.Assembly]::LoadFrom("$FilePath")

[Hjson.IJsonReader]::new()

[Hjson.hjson]::Load("$scriptRoot\test.hjson")

Я пытаюсь следовать примерам, чтобы получить основы:
Метод чтения: https://github.com/hjson/hjson-cs

# var jsonObject = HjsonValue.Load(filePath).Qo();

$jsonTempData = [Hjson.HjsonValue]::Load("$scriptRoot\test.hjson")
$jsonObject = [Hjson.JsonUtil]::Qo($jsonTempData)
$jsonObject

но на выходе отсутствуют значения:

PS D:\OneDrive\PS-HJSON> $jsonObject

Key       Value
---       -----
hello
text
quote
otherwise
abc-123
commas
but
trailing
multiline
number
negative
yes
no
null
array
array2


PS D:\OneDrive\PS-HJSON>

Так что я не вижу ценностей. Почему это не работает как объекты JSON?

И когда я пытаюсь перебрать ключи:

foreach ( $item in $jsonObject) {
    $item.Key, $item.Value
}

Я получил это:

При попытке перечисления коллекции произошло следующее исключение: "Операция недопустима из-за текущего состояния объекта".

Я уверен, что что-то упустил, но я не знаю C# достаточно, чтобы знать, что делать.

1 ответ

Решение

Библиотека написана так, что не очень хорошо работает с тем, как PowerShell отображает данные, для которых нет информации о формате.

Зачем

  • JsonValue (тип, испускаемый Hjson.Load) более или менее словарь string в JsonPrimitive (или больше JsonValue для вложения).

  • Причина, по которой вы не видите никаких значений при выводе переменной, заключается в том, что PowerShell по умолчанию просто преобразует объекты в строку. JsonValue преобразование в строку - просто пустая строка, поэтому она выглядит как нулевое значение, но это полный объект.

  • Причина, по которой это бросает InvalidOperationException ссылка на перечисление происходит потому, что PowerShell пытается перечислить все, что реализует IEnumerable, Но, JsonPrimitive будет выдавать, когда вы пытаетесь перечислить его, если реальное значение объекта не является массивом.

Решение

Индивидуальные ценности

Если вы хотите получить индивидуальное значение, вы можете позвонить JsonPrimitive.ToValue метод. Это преобразует JsonPrimitive к эквивалентному типу.NET.

$jsonObject = [Hjson.HjsonValue]::Load("myFile.hjson")
$jsonObject['MyKey'].ToValue()

Проблема в том, что он будет работать только с ключами, которые, как вы знаете, являются примитивами. Это означает, что для полного преобразования в обычный отображаемый тип вам необходимо перечислить JsonValueпроверьте, если это JsonPrimitive или же JsonObjectтогда либо позвони ToValue или вернитесь во вложенный объект.

Полная конверсия

Более простой подход может состоять в том, чтобы просто преобразовать его в json, так как PowerShell намного лучше справляется с этим.

$jsonObject = [Hjson.HjsonValue]::Load("myFile.hjson")
$stringWriter = [System.IO.StringWriter]::new()
$jsonObject.Save($stringWriter, [Hjson.Stringify]::Plain)
$hjsonAsPSObject = $stringWriter.GetStringBuilder().ToString() | ConvertFrom-Json

Save Метод принимает путь, поток или TextWriter, StringWriter Объект это простой способ получить строку из чего-то, что принимает TextWriter,

Как сказать?

Если вы когда-либо сталкивались с объектом, который, по вашему мнению, должен иметь значение, но отображать его так, как будто он не имеет значения, есть большая вероятность, что он просто не отображается прямо в PowerShell. В этом сценарии самый простой способ, которым вы могли бы протестировать, - это попробовать некоторые из них:

# Shows you the objects type, or if it really is $null it will throw
$jsonObject['jsonKey'].GetType()

# This will tell you the properties and methods available on an object
# but in this case it would throw due to the enumeration funk.
$jsonObject['jsonKey'] | Get-Member

# This gets around the enumeration issue.  Because there's no pipeline,
# Get-Member gives you the members for the type before enumeration.
Get-Member -InputObject ($jsonObject['jsonKey'])
Другие вопросы по тегам