-1

As in Passing bash variable to jq, we should be able to use a JQ variable as $VAR in a jq expression.

projectID=$(jq -r --arg EMAILID "$EMAILID" '
        .resource[]
        | select(.username==$EMAILID) 
        | .id' file.json
)

SO to extract project_id from the json file sample.json.

{
    "dev": {
        "gcp": {
            "project_id": "forecast-dev-1234",
            "project_number": "123456789",
            "endpoint_id": "6837352639743655936"
        }
    }
}

Run the JQ expression using a variable but did not work.

# TARGET=dev
$ jq -r --arg TARGET "${TARGET}" '.$TARGET.gcp.project_id' sample.json
-----
jq: error: syntax error, unexpected '
.$TARGET.gcp.project_id 
 (Unix shell quoting issues?) at <top-level>, line 1:
.$TARGET.gcp.project_id 
jq: error: try .["field"] instead of .field for unusually named fields at <top-level>, line 1:
.$TARGET.gcp.project_id
jq: 2 compile errors

Please help understand why and how to use the variable to form an expression to extract project_id.

JQ Manual does not provide clear explanation for variable and ---arg. Is there a good resource that clearly explain JQ variable and how to use it?

Another way to set the exit status is with the halt_error builtin function.

  • --arg name value:
    This option passes a value to the jq program as a predefined variable. If you run jq with --arg foo bar, then $foo is available in the program and has the value "bar". Note that value will be treated as a string, so --arg foo 123 will bind $foo to "123".

Workaround

Using interpolation.

$ TARGET=dev
$ jq -r --arg TARGET "${TARGET}" '."\($TARGET)".gcp.project_id' sample_interpolation.json
-----
forecast-dev-1234

Version

jq --version
---
jq-1.64l
mon
  • 18,789
  • 22
  • 112
  • 205
  • 1
    With the field name string value `dev` stored in a variable `$TARGET`, both `.[$TARGET]` and `."\($TARGET)"` will traverse to `.dev`. But you can only pass and store strings (or other JSON values using `--argjson`), not jq expressions that can be evaluated. However, you can pass something (e.g. an array of field name strings) and parse it manually (e.g. iterate over the array and traverse accordingly). – pmf Aug 07 '22 at 22:05

1 Answers1

2

You're using variables fine, the problem is that object-identifier syntax doesn't allow general expressions. It's a shorthand syntax for when the key you're looking up is a fixed identifier-like string, like .foo or .project_id. As noted in the manual, you can use the more general generic object index filter for arbitrary keys including those that are calculated by some expression, such as .[$TARGET]:

$ TARGET=dev
$ jq -r --arg TARGET "${TARGET}" '.[$TARGET].gcp.project_id' sample.json
forecast-dev-1234
Weeble
  • 17,058
  • 3
  • 60
  • 75