1

I'm using Bash to run the following script snippet on a Linux box.

JSON file contents: [ { "id": 123456, "firstName": "John", "lastName": "Smith", "email": "[email protected]" } ]


The JSON file is stored in the ${data[0]} array which is piped into the Bash script.


Bash script:

trafficEmployeeId=123456 cat "${data[0]}" | jq --arg employeeId $trafficEmployeeId '.[] | select(.id == $employeeId) | .firstName'


And the output from the script should be John. But I get nothing.

0

2 Answers 2

2

Even if you assigned shell variable trafficEmployeeId with a number it will be passed into jq script as a string argument.
The solution is to parse the argument as a number with jq's tonumber function.
The second moment is that data[0] contains the array with only one object, so it's enough to access it directly with .[0] and apply simple if operator condition.

Complete solution:

trafficEmployeeId=123456
echo "${data[0]}" | jq --arg employeeId "$trafficEmployeeId" '.[0] 
      | if .id == ($employeeId | tonumber) then .firstName else empty end'

The output:

"John"
3
  • On newer versions of jq, one could also use --argjson instead of tonumber.
    – dhag
    Commented Oct 20, 2017 at 16:47
  • Thanks for the advice. I'll try this solution and get back to you.
    – Berni
    Commented Oct 20, 2017 at 18:53
  • Your answer led me to the correct solution. Thanks a lot!
    – Berni
    Commented Oct 20, 2017 at 19:23
0

The main issue in the code is that you're calling cat with ${data[0]} as its argument. This will cause cat to try to open a file with that as its filename. This may be what you mean by "The JSON file is stored in the ${data[0]} array", but if it means that the file is literally stored in the array, then you need to use printf to pass that data to jq.

There's an additional issue with you trying to compare a number (in the JSON document) with a string (the value of $employeeId in the jq expression). This is easily remedied by using --argjson in place of --arg. Using --argjson will make jq assume that the value of the variable that you create is appropriately JSON encoded already.

Your modified script becomes

#!/bin/sh

id=123456
jq --argjson id "$id" '.[] | select(.id == $id).firstName' file.json

or, if you want to use the value in ${data[0]}:

#!/bin/bash

# other code here setting data[0] to some JSON document data.

id=123456

printf '%s\n' "${data[0]}" |
jq --argjson id "$id" '.[] | select(.id == $id).firstName'

If the query id comes from user input or some other external process, it may be safer to still use --arg and to convert the value in the document to a string to compare with in the select() expression:

jq --arg id "$id" '.[] | select((.id|tostring) == $id).firstName'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .