jq1.5 - cannot use arg to specify path

Created on 5 Oct 2017  Â·  8Comments  Â·  Source: stedolan/jq

Attempting to use an arg as the sole 'path string' does not give expected results

read -r -d '' JSON_DATA <<'EOF'
{
  "source": {
    "url": "https://github.com/stedolan/jq/"
  }
}
EOF

echo "$JSON_DATA" | jq --raw-output --arg my_path_var ".source.url" '$my_path_var'

expected results:

https://github.com/stedolan/jq/

actual results:

.source.url
feature request not a bug

Most helpful comment

@beantaxi Please use --argjson.

All 8 comments

There are two problems with your example:

(1) JSON_DATA is missing a closing right-brace
(2) It looks like you meant:

echo "$JSON_DATA" | jq ".source.url"

If you wrote: jq -n --arg foo bar '$foo'

you'd expect (and you'd get):

"bar"

If you wrote: jq -n --arg foo bar '$foo'

you'd expect (and you'd get):

"bar"

The point of my issue is that jq is expanding the argument, but not using its value as the path.

My example is just an example. My real world use case is that I'm assigning the argument the value of a bash variable, e.g.:

echo "$JSON_DATA" | jq --raw-output --arg my_path_var "$my_bash_path_var" '$my_path_var'

If $my_bash_path_var contains .source.url, then I expect jq to act as though I had done this:

echo "$JSON_DATA" | jq --raw-output '.source.url'

Since jq allows me to use the argument in many ways other than the initial path... e.g.

echo "$JSON_DATA" | jq --raw-output --arg my_url_var "$bash_url_var" '. | select( .source.url == $my_url_var )'

Shouldn't I be able to use the value of a variable to denote the path, as well? Instead, it just prints the value of the variable, and doesn't 'process it as path'.

Indeed jq does not currently have an ‘eval’ function. So evaluating a jq path expression dynamically is not possible. But jq does support evaluating array path expressions, e.g. using getpath/1. So you could, for example, pass in an array path expression, and call getpath($p).

Correct, there's no eval (yet), and --arg (and all its variants) only deals with _data_.

You could pass a "path expression" as an array of keys:

$ echo "$JSON_DATA" | jq --arg path '["source","url"]' 'getpath($path)'

We have other issues open for eval, so I'll close this.

The "path expression" approach above does not work (for me). Copy/pasting into a new file ...

read -r -d '' JSON_DATA <<'EOF'
{
  "source": {
    "url": "https://github.com/stedolan/jq/"
  }
}
EOF

echo "$JSON_DATA" | jq --arg path '["source","url"]' 'getpath($path)'

Sourcing the above gives this error:

$ source /tmp/path.jq 
jq: error (at <stdin>:5): Path must be specified as an array
$ jq --version
jq-1.6

Is there a different way to approach this in 2020? Thanks!

@beantaxi Please use --argjson.

Works great - thanks much, esp for the fast response!

$ JSON='{"foo": {"bar": {"baz": "luhrmann"}}}'
$ jq --argjson path '["foo", "bar", "baz"]' 'getpath($path)' <<<"$JSON"
"luhrmann"
Was this page helpful?
0 / 5 - 0 ratings