用于 PowerShell 的 HJSON C# 库

HJSON C# library for PowerShell

我正在尝试为 PowerShell 使用 HJSON C# 库: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#read

# 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
}

我知道了:

The following exception occurred while trying to enumerate the collection: "The operation is invalid due to the current state of the object. "

我确定我遗漏了什么,但我对 C# 的了解还不足以知道该怎么做。

库的编写方式不适用于 PowerShell 显示数据的方式,它没有格式信息。

为什么

  • JsonValueHjson.Load 发出的类型)或多或少是 stringJsonPrimitive(或更多 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 方法采用路径、流或 TextWriterStringWriter 对象只是从接受 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'])