用于提取 json 数据的 PowerShell 2.0 脚本

PowerShell 2.0 script to extract json data

更新 - Powershell 5.1 的解决方案非常简单。我单独发布了一个答案

我正在尝试我的第一个 Powershell 脚本(Windows 7 中的 2.0 版)。我正在从文件中读取以下 json 文本(该部分有效)。我想获得“public_url”的值。我在下面的脚本中遇到的错误是“

Select-Object : Property "tunnels" cannot be found

我是第一次使用 Powershell,我不太了解如何导航对象。提前致谢,

我的json文件内容:

  {
     "tunnels":[
        {
           "name":"command_line",
           "uri":"/api/tunnels/command_line",
           "public_url":"tcp://8.tcp.ngrok.io:12716",
           "proto":"tcp",
           "config":{
              "addr":"localhost:32400",
              "inspect":false
           },
           "metrics":{
              "conns":{
                 "count":0,
                 "gauge":0,
                 "rate1":0,
                 "rate5":0,
                 "rate15":0,
                 "p50":0,
                 "p90":0,
                 "p95":0,
                 "p99":0
              },
              "http":{
                 "count":0,
                 "rate1":0,
                 "rate5":0,
                 "rate15":0,
                 "p50":0,
                 "p90":0,
                 "p95":0,
                 "p99":0
              }
           }
        }
     ],
     "uri":"/api/tunnels"
  }

我的 Powershell 脚本:

function ConvertFrom-Json20([object] $item){ 
  add-type -assembly system.web.extensions
  $ps_js=new-object system.web.script.serialization.javascriptSerializer

  #The comma operator is the array construction operator in PowerShell
  return ,$ps_js.DeserializeObject($item)
}

$content = get-content -path "c:\path\to\json.txt"
$json = ConvertFrom-Json20($content)

$url = $json | select -expand tunnels | select public_url

echo "url=>" $url

继续我的评论。 只需使用 JSON cmdlet 升级到最新的 WinPS,不要尝试重新发明轮子。

Windows 管理框架 5.1

https://www.microsoft.com/en-us/download/details.aspx?id=54616

Windows Management Framework 5.1 includes updates to Windows PowerShell, Windows PowerShell Desired State Configuration (DSC), Windows Remote Management (WinRM), Windows Management Instrumentation (WMI). Release notes: https://go.microsoft.com/fwlink/?linkid=839460

Get-Command -Name '*json*' | Format-Table -AutoSize
# Results
<#
CommandType Name             Version Source                      
----------- ----             ------- ------                      
Cmdlet      ConvertFrom-Json 3.1.0.0 Microsoft.PowerShell.Utility
Cmdlet      ConvertTo-Json   3.1.0.0 Microsoft.PowerShell.Utility
#>

PowerShell 本机使用 JSON、XML,并且您可以访问所有 .Net,因此,您可以使用 JSON.

的 .Net 命名空间

只需查看有关如何使用它们的帮助文件。有完整的解释和例子。

# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-Help).Parameters
(Get-Command -Name Get-Help).Parameters.Keys
Get-help -Name Get-Help -Examples
Get-help -Name Get-Help -Full
Get-help -Name Get-Help -Online


(Get-Command -Name ConvertFrom-Json).Parameters
(Get-Command -Name ConvertFrom-Json).Parameters.Keys
Get-help -Name ConvertFrom-Json -Examples
Get-help -Name ConvertFrom-Json -Full
Get-help -Name ConvertFrom-Json -Online


(Get-Command -Name ConvertTo-Json).Parameters
(Get-Command -Name ConvertTo-Json).Parameters.Keys
Get-help -Name ConvertTo-Json -Examples
Get-help -Name ConvertTo-Json -Full
Get-help -Name ConvertTo-Json -Online

根据您的评论更新

使用上面的方法,您可以通过点引用和/或索引导航 JSON 对象。

$JsonData = '
{
     "tunnels":[
        {
           "name":"command_line",
           "uri":"/api/tunnels/command_line",
           "public_url":"tcp://8.tcp.ngrok.io:12716",
           "proto":"tcp",
           "config":{
              "addr":"localhost:32400",
              "inspect":false
           },
           "metrics":{
              "conns":{
                 "count":0,
                 "gauge":0,
                 "rate1":0,
                 "rate5":0,
                 "rate15":0,
                 "p50":0,
                 "p90":0,
                 "p95":0,
                 "p99":0
              },
              "http":{
                 "count":0,
                 "rate1":0,
                 "rate5":0,
                 "rate15":0,
                 "p50":0,
                 "p90":0,
                 "p95":0,
                 "p99":0
              }
           }
        }
     ],
     "uri":"/api/tunnels"
  }
' | 
ConvertFrom-Json

$JsonData
# Results
<#
tunnels                                                                                                                    uri         
-------                                                                                                                    ---         
{@{name=command_line; uri=/api/tunnels/command_line; public_url=tcp://8.tcp.ngrok.io:12716; proto=tcp; config=; metrics=}} /api/tunnels
#>

$JsonData.tunnels
# Results
<#
name       : command_line
uri        : /api/tunnels/command_line
public_url : tcp://8.tcp.ngrok.io:12716
proto      : tcp
config     : @{addr=localhost:32400; inspect=False}
metrics    : @{conns=; http=}
#>

$JsonData.uri
# Results
<#
/api/tunnels
#>

$JsonData.uri.Split('/')
# Results
<#
api
tunnels
#>

$JsonData.uri.Split('/')[-1]
# Results
<#
tunnels
#>

至于你的东西……好吧,它从来都不是一个对象。只是一个字符串。

这并不像你想象的那样有效

function ConvertFrom-Json20([object] $item)
{ 
  Add-Type -Assembly System.Web.Extensions

  $ps_js = New-Object System.Web.Script.Serialization.JavascriptSerializer
  return
  $ps_js.DeserializeObject($item)
}

($content = Get-Content -path 'D:\Scripts\json.txt')

($json = ConvertFrom-Json20($content))
# Results
<#
Nothing is returned
#>

# So this would never work
# Results
<#
$url = $json | select -expand tunnels | select public_url

echo "url=>" $url
#>

所以,读取数据并抓取字符串

(Get-Content -path 'D:\Scripts\json.txt').Trim() | 
Select-String -Pattern 'uri.*'
# Results
<#
"uri":"/api/tunnels/command_line",
"uri":"/api/tunnels"
#>

((Get-Content -path 'D:\Scripts\json.txt').Trim() | 
Select-String -Pattern 'uri.*')[-1] -replace '"' -split('/')
# Results
<#
uri:
api
tunnels
#>
(((Get-Content -path 'D:\Scripts\json.txt').Trim() | 
Select-String -Pattern 'uri.*')[-1] -replace '"' -split('/'))[-1]
# Results
<#
tunnels
#>

要从那个 JSON 文件中获取一个对象,在 PSv2 中,你会说做这样的事情。

[void][System.Reflection.Assembly]::LoadWithPartialName('System.Web.Extensions')

$JsonData    = Get-Content -Path 'D:\Scripts\Json.txt'
$Serializer  = New-Object System.Web.Script.Serialization.JavaScriptSerializer
($JsonObject = $Serializer.DeserializeObject($JsonData))
# Results
<#
Key     Value                                                                 
---     -----                                                                 
tunnels {System.Collections.Generic.Dictionary`2[System.String,System.Object]}
uri     /api/tunnels 
#>

或者这样...

($JsonObject = New-Object PSObject -Property $Serializer.DeserializeObject($JsonData))
# Results
<#
tunnels                                                                uri         
-------                                                                ---         
{System.Collections.Generic.Dictionary`2[System.String,System.Object]} /api/tunnels
#>

...然后点引用

$JsonObject.tunnels
# Results
<#
Key        Value
---        -----
name       command_line
uri        /api/tunnels/command_line
public_url tcp://8.tcp.ngrok.io:12716 
proto      tcp
config     {[addr, localhost:32400], [inspect, False]}
metrics    {[conns, System.Collections.Generic.Dictionary
#>

$JsonObject.uri
# Results
<#
/api/tunnels
#>

这是 Powershell 5.1 的简​​单答案

$json = get-content -path "c:\path\to\json.txt" | ConvertFrom-Json
$url = $json.tunnels.public_url