2

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?

Christian Bongiorno
  • 5,150
  • 3
  • 38
  • 76

2 Answers2

1

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"
]
Morteza
  • 642
  • 7
  • 17
1

You can use:

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

To get the "first" hash in that hierarchy.

[*] behaves like the spread-operator in Groovy

cfrick
  • 35,203
  • 6
  • 56
  • 68
  • I literally discovered the exact same thing now. If I wanted a flattened list, element 0, how might I do that? If you can update the answer that'd be great. I mean, you answered it correctly so you win the prize, but some color would be nice – Christian Bongiorno Jul 29 '20 at 18:57