我想从PowerShell的JSON文件中检索数据.我有以下JSON数据:

{
  "id": "abcxyz",
  "data": {
    "a": {
        "abc": "xyz"
    },
    "b": [
      {
        "bId": 2001,
        "bData": {
          "bAbc": [
            {
              "bAbcX": 123,
              "bAbcY": 456,
              "bAbcZ": "b1AbcZ0"
            },
            {
              "bAbcX": 312,
              "bAbcY": 654,
              "bAbcZ": "b1AbcZ1"
            }
          ],
          "bDef": [
            {
              "bDefX": 456,
              "bDefY": 654,
              "bDefZ": "b1DefZ0"
            },
            {
              "bDefX": 789,
              "bDefY": 987,
              "bDefZ": "b1DefZ1"
            }
          ]
        }
      },
      {
        "bId": 2002,
        "bData": {
          "bAbc": [
            {
              "bAbcX": 123,
              "bAbcY": 456,
              "bAbcZ": "b2AbcZ0"
            },
            {
              "bAbcX": 312,
              "bAbcY": 654,
              "bAbcZ": "b2AbcZ1"
            }
          ],
          "bDef": [
            {
              "bDefX": 456,
              "bDefY": 654,
              "bDefZ": "b2DefZ0"
            },
            {
              "bDefX": 789,
              "bDefY": 987,
              "bDefZ": "b2DefZ1"
            }
          ]
        }
      },
      {
        "bId": 2003,
        "bData": {
          "bAbc": [
            {
              "bAbcX": 123,
              "bAbcY": 456,
              "bAbcZ": "b3AbcZ0"
            },
            {
              "bAbcX": 312,
              "bAbcY": 654,
              "bAbcZ": "b3AbcZ1"
            }
          ],
          "bDef": [
            {
              "bDefX": 456,
              "bDefY": 654,
              "bDefZ": "b3DefZ0"
            },
            {
              "bDefX": 789,
              "bDefY": 987,
              "bDefZ": "b3DefZ1"
            }
          ]
        }
      }
    ]
  }
}

我想用PowerShell中的JSONPath $.data.b[*].bData.bAbc[0].bAbcZ检索数据.预期结果为:

[
  "b1AbcZ0",
  "b2AbcZ0",
  "b3AbcZ0"
]

JSONPath在https://jsonpath.com/中工作,以下是我try 在PowerShell中检索它的方式:

$JSON = Get-Content ".\test.json" | Out-String | ConvertFrom-Json
$JSON.data.b[*].bData.bAbc[0].bAbcZ

但当我在PowerShell中try 时,*是无效的,这是输出:

+ $JSON.data.b[*].bData.bAbc[0].bAbcZ
+              ~
Array index expression is missing or not valid.

+ $JSON.data.b[*].bData.bAbc[0].bAbcZ
+               ~
You must provide a value expression following the '*' operator.

+ $JSON.data.b[*].bData.bAbc[0].bAbcZ
+               ~
Unexpected token ']' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : MissingArrayIndexExpression

我也try 使用$JSON.data.b.bData.bAbc[0].bAbcZ,但它只检索第一个数据,即b1AbcZ0.PowerShell对象中的JSON通配符(*)的类似功能是什么?

推荐答案

您可以通过递归地首先使用unrolling个JSON对象来使用类似于JSONPath的查询.然后,您可以使用Where-Object命令或.Where{}方法按路径过滤JSON.

下面是一个平坦化JSON的函数.它输出带有属性PathValue的序列[PSCustomObject]:

Function Expand-Json {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, ValueFromPipeline)] [PSCustomObject] $InputObject,
        [Parameter()] [string] $Path
    )
    
    process {
        # Iterate the properties of InputObject
        foreach( $prop in $InputObject.PSObject.Properties ) {

            # Full path of the current property
            $propertyPath = "$Path.$($prop.Name)"

            # Output current property with path
            [PSCustomObject]@{ Path = $propertyPath; Value = $prop.Value }

            if( $prop.Value -is [PSCustomObject] ) {
                # Process child object recursively
                Expand-Json -InputObject $prop.Value -Path $propertyPath
            }
            elseif( $prop.Value -is [Collections.IList] ) {
                # Iterate array and process each element recursively
                $i = 0
                foreach( $item in $prop.Value ) {
                    $itemPath = "$propertyPath<$i>"; $i++
                    Expand-Json -InputObject $item -Path $itemPath
                }
            }
        }
    }
}

Usage example:

$JSON = Get-Content ".\test.json" -Raw | ConvertFrom-Json

# Unroll the JSON
$flatJSON = $JSON | Expand-Json   

# Filter by path - this outputs an array
$filteredJSON = $flatJSON | Where-Object Path -like '.data.b<*>.bData.bAbc<0>.bAbcZ'

# Convert data back to JSON string
$filteredJSON.Value | ConvertTo-Json

Output:

[
  "b1AbcZ0",
  "b2AbcZ0",
  "b3AbcZ0"
]

Notes:

  • 路径语法.data.b<*>.bData.bAbc<0>.bAbcZ与JSONPath略有不同,以便更容易与PowerShell -like操作符一起使用.
    • 没有根对象令牌$,因为此字符对于PowerShell字符串插补具有特殊意义.
    • 数组索引使用尖括号<>表示,因为方括号[]对于-like运算符具有特殊意义(它们表示一系列字符,请参见about Wildcards).
  • 功能Expand-Json在概念上是清楚的,但效率不是很高.通常,由于参数绑定开销,递归PowerShell函数往往相对较慢.如果性能是最重要的,有几种方法可以显著提高性能,例如使用类或内联C#.

Json相关问答推荐

PowerShell脚本-替换json数组(转义$var将被视为不带双引号的文本)

ArcGIS json到Geojson的变换

如何在我的响应模型中修复此问题:[期望的值类型为';Map<;Dynamic,Dynamic&>;,但获得的值类型为';NULL&39;]

如何在JSONata对象中迭代并向数组添加新字段?

Azure数据工厂-WEB活动输出赢得';t返回JSON

如何使NiFi将数据库单列中的多个值转化为Solr索引中的数组?

如何从条带订阅响应对象中正确获取 struct 项?

提交后使用 Rails 7 结合 JSON 标签进行标记

坚持弄清楚如何使用 api 响应来调用以从不同的链接检索响应

下一个 Js 部署在 getStaticPath 函数上失败:在 JSON.parse 的位置 0 的 JSON 中出现意外的令牌 < 但在本地运行

ASP.NET MVC - 将 Json 结果与 ViewResult 结合起来

使用非美国日期格式时,JsonConvert.DeserializeObject 无法将字符串转换为 DateTime

使用 API 搜索维基百科

Swift :将 struct 转换为 JSON?

使用适用于 Python 的 Google API - 我从哪里获取 client_secrets.json 文件?

如何在 Java 中将 YAML 转换为 JSON?

如何在spark 上将json字符串转换为数据帧

如何在 JAVA 中对 JSONArray 进行排序

JSON.stringify 向我的 Json 对象添加额外的 \ 和 "" 的问题

TypeError:使用Python解析JSON时字符串索引必须是整数?