gpt4 book ai didi

json - 通过 Powershell 中的变量解析/访问嵌套 JSON/Hashtable 数据时出现问题

转载 作者:行者123 更新时间:2023-12-01 15:33:43 26 4
gpt4 key购买 nike

我正在尝试通过 Powershell 动态解析和构建一些传入的 JSON 文件的数据结构(这将是非标准结构),然后处理这些文件中的数据并交给它们到下一步。

作为其中的一部分,我试图将 JSON 文件的数据结构构建成一个数据路径列表,以便我解析并从中获取数据,以便我可以处理数组、嵌套 JSON对象等等。到现在为止还挺好。

我陷入某种 Powershell 特性的地方是通过变量处理 2+ 级别的深度。让我给你一个很好的代码块来演示这个问题......

# Generate a Quick JSON file with different data types & levels
[object]$QuickJson = @'
{
"Name" : "I am a JSON",
"Version" : "1.2.3.4",
"SomeBool" : true,
"NULLValue" : null,
"ArrayOfVersions" : [1.0,2.0,3.0],
"MyInteger" : 69,
"NestedJSON" : {
"Version" : 5.0,
"IsReady" : false
},
"DoubleNestedJSON" : {
"FirstLevel" : 1,
"DataValue" : "I am at first nested JSON level!",
"Second_JSON_Level" : {
"SecondLevel" : 2,
"SecondDataValue" : "I am on the 2nd nested level"
}
}
}
'@

# Import our JSON file into Powershell
[object]$MyPSJson = ConvertFrom-Json -InputObject $QuickJson
# Two quick string variables to access our JSON data paths
[string]$ShortJsonPath = "Name"
[string]$NestedJsonPath = "NestedJson.Version"
# Long string to access a double-nested JSON object
[string]$LongNestedJsonPath = "DoubleNestedJSON.Second_JSON_Level.SecondDataValue"

# Both of these work fine
Write-Host ("JSON Name (Direct) ==> " + $MyPSJson.Name)
Write-Host ("JSON Name (via Variable) ==> " + $MyPSJson.$ShortJsonPath)

# The following way to access a single nested Json Path works fine
Write-Host ("Nested JSON Version (via direct path) ==> " + $MyPSJson.NestedJson.Version)
# And THIS returns an empty line / is where I fall afoul of something in Powershell
Write-Host ("Nested JSON Version (via variable) ==> " + $MyPSJson.$NestedJsonPath)

# Other things I tried -- all returning an empty line / failing in effect
Write-Host ("Alternate Nested JSON Version ==> " + $($MyPSJson.$NestedJsonPath))
Write-Host ("Alternate Nested JSON Version ==> " + $MyPSJson.$($NestedJsonPath))
Write-Host ("Alternate Nested JSON Version ==> " + $($MyPSJson).$($NestedJsonPath))

# Similarly, while THIS works...
$MyPSJson | select-object -Property NestedJSON
# This will fail / return me nothing
$MyPSJson | select-object -Property NestedJSON.Version

...在围绕此进行大量研究时,我遇到了将其转换为 Hashtable 的建议——但遗憾的是,这也有同样的问题。因此,使用上面的代码片段,以下将 JSON 对象转换为哈希表。
# Same problem with a hash-table if constructed from the JSON file...
[hashtable]$MyHash = @{}
# Populate $MyHash with the data from our quickie JSON file...
$QuickJson | get-member -MemberType NoteProperty | Where-Object{ -not [string]::IsNullOrEmpty($QuickJson."$($_.name)")} | ForEach-Object {$MyHash.add($_.name, $QuickJson."$($_.name)")}

# ... and even then -- $MyHash."$($NestedJsonPath)" -- fails, while a single level deep string works fine in the variable! :(

所以很明显,我遇到了 Powershell 内部逻辑问题的“某些东西”,但我不能让 Powershell 对为什么会过分帮助。添加一个“-debug”或类似的尝试增加详细程度并没有帮助阐明这一点。

我怀疑这类似于本文中提出的项目 ( https://blogs.technet.microsoft.com/heyscriptingguy/2011/10/16/dealing-with-powershell-hash-table-quirks/),但只是针对变量。

我没有任何运气在 Powershell 语言规范中找到任何明显的东西(据我所知,3.0 仍然是最新的 - https://www.microsoft.com/en-usdownload/details.aspx?id=36389)。它可能在那里,我可能只是想念它。

任何有关如何让 Powershell 很好地发挥作用的建议将不胜感激。我不确定 Powershell 如何/为什么可以使用简单的字符串,但这里的 'something.somethingelse' 类型字符串似乎存在问题。

谢谢你。

对原文的进一步说明和增补:

似乎有几个问题需要解决。一个是“处理单个嵌套级别”。对此的“快速修复”似乎是使用“Invoke-Expression”来解析语句,例如(重要 - 请注意第一个变量的反引号!):
iex "`$MyPSJson.$NestedJsonPath"

Invoke-Expression 的使用也适用于多嵌套情况:
iex "`$MyPSJson.$LongNestedJsonPath"

提到的另一种方法是使用多个选择语句......但我无法让它与多嵌套对象一起使用(Powershell 似乎由于某种原因无法正确解决这些问题)。

因此,例如在这种情况下:
($MyComp | select $_.DoubleNestedJSON | select FirstLevel)

Powershell 返回
FirstLevel    
----------

...而不是实际的数据值。所以 - 就目前而言,由于 Powershell 显然没有解决它们,因此似乎选择不适用于多级嵌套对象?

最佳答案

当你写类似的东西时

$MyPSJson.Name

这将尝试检索名为 Name 的成员来自对象 $MyPSJson .如果没有这样的成员(member),你会得到 $null .

现在,当您使用成员名称的变量执行此操作时:
$MyPSJson.$ShortJsonPath

这几乎相同,因为名称存储在 $ShortJsonPath 中的成员被查找并检索其值。这里没有惊喜。

当您尝试使用对象上不存在的成员时,例如
$MyPSJson.$NestedJsonPath
# equivalent to
# $MyPSJson.'NestedJSON.Version'

你会得到 $null ,如前所述。 .运算符只会访问作为其左侧表达式结果的确切对象的成员。它永远不会像您期望的那样通过成员层次结构。坦率地说,我不知道有一种语言可以这样工作。

它适用于 Invoke-Expression 的原因是,您有效地转换了 $NestedJsonPath将字符串转换为表达式的一部分,导致:
$MyPSJson.NestedJSON.Version

其中 Invoke-Expression然后评估。

当然,您可以定义自己的以这种方式工作的函数(我更喜欢使用它而不是使用 Invoke-Expression ,这是一个很少使用的 cmdlet(如果有的话)(见鬼,它是 eval 用于 PowerShell - 很少带有 eval 的语言提倡使用它)):
function Get-DeepProperty([object] $InputObject, [string] $Property) {
$path = $Property -split '\.'
$obj = $InputObject
$path | %{ $obj = $obj.$_ }
$obj
}

PS> Get-DeepProperty $MyPSJson NestedJson.Version
5,0

你甚至可以把它做成一个过滤器,这样你就可以在管道上更自然地使用它:
filter Get-DeepProperty([string] $Property) {
$path = $Property -split '\.'
$obj = $_
$path | %{ $obj = $obj.$_ }
$obj
}

PS> $MyPSJson | Get-DeepProperty nestedjson.version
5,0

关于json - 通过 Powershell 中的变量解析/访问嵌套 JSON/Hashtable 数据时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41875328/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com