skip to Main Content

I have the following dataset :

{
  "data": {
    "system": [
      {
        "login": "vault keystore password",
        "password": "123456"
      },
      {
        "login": "vault keystore masked",
        "password": "MASK-789101112"
      },
      {
        "login": "vault salt",
        "password": "toto"
      },
      {
        "login": "vault iteration",
        "password": "10"
      },
      {
        "login": "keystore Alias",
        "password": "vault"
      }
    ]
  }
}

I want to retrieve in my shell the password when login is "vault keystore password".

The closest that I have found is :
.data.system |map_values(select(.login == "vault keystore password"))[].password
but it returns me not the expected output (I wanted 123456):

"123456"
"toto"
"vault"

Could you please explain me the correct syntax ?

3

Answers


  1. First iterare over the array, then select by criteria:

    jq -r '.data.system[] | select(.login == "vault keystore password").password'
    
    # or by importing a string from outside dynamically
    
    jq -r --arg login "vault keystore password" '
      .data.system[] | select(.login == $login).password
    '
    
    123456
    
    Login or Signup to reply.
  2. Using just map(select(..)) will solve your problem.

    .data.system | map(select(.login == "vault keystore password"))[].password
    

    By the official docs, using map_values() should also work. For some reason jq (jq-1.6) is misbehaving (possibly a bug) while using for this filter. The same filter works well with gojq.

    Per builtin.jq, map_values(..) is just

    def map_values(f): .[] |= f;
    

    so essentially, your filter comes down to

    .data.system[] |= select(.login == "vault keystore password")
    

    which is producing 3 objects inside the list system, which is incorrect. On the other hand gojq handles it correctly. I would argue the whole issue is around the update assignment operator of jq (i.e. |=), which is known to have caused issues in the past. See https://github.com/stedolan/jq/issues/2051

    jq has been stuck in a release limbo for a while now (https://github.com/stedolan/jq/issues/2305). So until the time a new release > 1.6 comes along, gojq would be an ideal replacement with much of the known issues fixed (those of jq).


    On gojq version 0.12.12

    echo '{"data":{"system":[{"login":"vault keystore password","password":"123456"},{"login":"vault keystore masked","password":"MASK-789101112"},{"login":"vault salt","password":"toto"},{"login":"vault iteration","password":"10"},{"login":"keystore Alias","password":"vault"}]}}' |
      gojq '.data.system | map_values(select(.login == "vault keystore password"))[].password' 
    

    produces

    "123456"
    
    Login or Signup to reply.
  3. You can do:

    .data.system | .[] |select(.login=="vault keystore password").password
    

    Demo

    Or as a jq command line:

    jq -r '.data.system | .[] |select(.login=="vault keystore password").password' 
    

    Or you can use ruby:

    ruby -r json -e 'JSON.parse($<.read)["data"]["system"].
        select{|h| h["login"]=="vault keystore password"}.
        each{|h| puts h["password"]}' 
    

    Either of those, given JSON on STDIN or as a file prints 123456 on STDOUT.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search