我正在尝试通过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/zh-cn/downloads/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显然无法解决选择问题,因此selects不适用于多层嵌套对象吗?
当您在字符串中提供所需的属性时,就像这样
[string]$NestedJsonPath = "NestedJson.Version"
Powershell寻找一个名为的属性NestedJSon.Version。它实际上并没有遍历属性,而是在寻找包含句点的字符串文字。实际上,如果我这样向您的JSON添加这样的属性。
NestedJSon.Version
[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" : 69, "NestedJSON" : { "Version" : 5.0, "IsReady" : false } }
我现在得到了价值,就像这样:
>$MyPSJson.$NestedJsonPath 69
取回值的最佳方法是使用两个单独的变量,如下所示。
$NestedJson = "NestedJson" $property = "Version" >$MyPSJson.$NestedJson.$property 5.0
或者,您也可以使用select语句,如下面的原始答案所示。
$MyPSJson | select $_.NestedJSON | select Version Version ------- 1.2.3.4
如果您使用多个Select-Object语句,它们将丢弃其他属性,并允许您更轻松地向下钻取您想要的值。