JSONPath: 提取数组的子集产生奇怪的结果

huangapple go评论53阅读模式
英文:

JSONPath: Extracting subset of array produces weird results

问题

您可以使用JSONPath表达式来获取单个数组项,但要注意JSONPath和jq的语法有所不同。以下是如何在JSONPath中获取单个数组项的示例表达式:

$.push.changes[0].commits[0].hash

这个表达式将返回您期望的单个哈希值。

请注意,JSONPath索引是从0开始的,所以我们使用[0]来获取数组中的第一个元素。与jq不同,JSONPath不会将字符串视为字符数组,所以您不需要额外的[0]来获取单个字符。

希望这可以帮助您解决问题。

英文:

I have this json:

{
  "push": {
    "changes": [
      {
        "commits": [
          {
            "hash": "b194ab92186b94de3f9493818c353e9bbedb38d4"
          }
        ]
      }
    ]
  }
}

And, I have the follow jq, code that works fine

cbongiorno at 5cg6203867 in ~/dev/sterling/pipeaas on master [+!?]
$ jq -re '.push.changes[].commits[].hash ' push.json # golden hash
b194ab92186b94de3f9493818c353e9bbedb38d4

which produces what I want.

I now try to use the JSONPath equivalent and this is where it gets strange:
If I try it here, I get and array size 1 with my hash:

$.push.changes[*].commits[*].hash
[
  "b194ab92186b94de3f9493818c353e9bbedb38d4"
]

So, that that yields and array, then I can just index that array, right?:

$.push.changes[*].commits[*].hash[0]
[
  "b"
]

I get the letter b - so now it's treating the string as a character array.

So, maybe it's an implementation problem. I tried this same path expression in groovy and I get something yet also different:

in jsonpath.groovy

@Grab(group = 'com.jayway.jsonpath', module = 'json-path', version = '2.4.0')
import com.jayway.jsonpath.*

stuff = JsonPath.parse(new File('push.json')).read('$.push.changes[*].commits[*].hash')
println(stuff)
$ groovy jsonpath.groovy

[b194ab92186b94de3f9493818c353e9bbedb38d4]

Ok, we have our array again. Now, let's get that 1 element:

@Grab(group = 'com.jayway.jsonpath', module = 'json-path', version = '2.4.0')
import com.jayway.jsonpath.*

stuff = JsonPath.parse(new File('push.json')).read('$.push.changes[*].commits[*].hash[0]')
println(stuff)
$ groovy jsonpath.groovy 
[]

So now, it's like the array has nothing at all?!

So, how do I get this single array item as a path expression?

答案1

得分: 1

你的问题不够清晰。但是,你的表达行为是正确的。你的 commits 是一个数组,所以你可以像 commits[*]commits[0] 一样操作它。但是 hash 字段不是数组。因此,JSONPath 将其视为 字符数组

我猜你想从 commits 数组中获取正确的 hash。所以你只需要将你的表达式修改为:

$.push.changes[*].commits[1].hash

假设你的 JSON 对象如下:

{
  "push": {
    "changes": [
      {
        "commits": [
          {
            "hash": "b194ab92186b94de3f9493818c353e9bbedb38d4"
          },
          {
              "hash":"secondHash"
          }
        ]
      }
    ]
  }
}

结果将是:

[
  "secondHash"
]
英文:

Your question is not clear enough. But, the behavior of your expression is correct. your commits is an array so you can behave it like commits[*] or commits[0]. But the hash field is not array. Because of that JSONPath treats it like arrays of characters.

I guess you want to get the right hash from commits array. so you just need your expression to be like:

$.push.changes[*].commits[1].hash

then assuming your JSON objet is like:

{
  "push": {
    "changes": [
      {
        "commits": [
          {
            "hash": "b194ab92186b94de3f9493818c353e9bbedb38d4"
          },
          {
              "hash":"secondHash"
          }
        ]
      }
    ]
  }
}

the result would be :

[
  "secondHash"
]

答案2

得分: 1

你可以使用以下代码来获取该层次结构中的“第一个”哈希值:

$.push.changes[0].commits[0].hash

[*] 的行为类似于Groovy中的扩展操作符。

英文:

You can use:

$.push.changes[0].commits[0].hash

To get the "first" hash in that hierarchy.

[*] behaves like the spread-operator in Groovy

huangapple
  • 本文由 发表于 2020年7月29日 07:19:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/63144161.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定