I am working with some location data and am querying an API with U.S. postal codes and returns a result like:
{
"resultStatus":"SUCCESS",
"zip5":"30301",
"defaultCity":"ATLANTA",
"defaultState":"GA",
"defaultRecordType":"PO BOX",
"citiesList":[],
"nonAcceptList":[{"city":"ATL","state":"GA"}]
}
I need to parse this to create output that also includes the full state name as well like:
ATLANTA, Georgia, GA, 30301
I created an associative array called States so that ${States[GA]}
would return the value Georgia
and tried to pass the array to jq as an argument like:
curl -sS <enpoint> |jq -r '"${States[\(.defaultState)]}, \(.defaultState), \(.defaultCity), \(.zip5)"'
Which resulted in the output ${States[GA]}, GA, ATLANTA, 30301
Is there anyway to pass and evaluate bash arrays in jq filters or similar?
Only option that I am seeing is to capture the output and pass through eval, but of course eval is evil... I am also going to be doing this thousands of times and combining with other external data from a file so I would prefer a better option than constructing convoluted strings with embedded bash arguments and eval'ing it.
EDIT
Forgot to mention I tried search jq 1.6 manual without luck and found this SO Post which led me to try passing States array as jq arg like so:
curl -sS <enpoint> |jq -r --arg states $States '"$states[\(.defaultState)], \(.defaultState), \(.defaultCity), \(.zip5)"'
but still no luck.
Workable script implementing steeldrivers answer:
#! /bin/bash
# Do once and save
statesJson=$(for state in "${!StatesArray[@]}"; do
printf '{"name":"%s",\n"value":"%s"}\n' $state "${StatesArray[$state]}";
done \
| jq -s 'reduce .[] as $i ({}; .[$i.name] = $i.value)');
# Read zip and 6 other values from SourceDataFile.csv
while IFS=',' read -r zip fileValue02 fileValue03 fileValue04 fileValue05 fileValue06 fileValue07; do
# Use zip from file to get expanded location data.
expandedLocationData=$(curl -sS '<apiEndpoint>' -H <Headers> --data "zip=$zip" |jq -r --argjson states "${statesJson}" '"\United States, US, ($states[.defaultState]), \(.defaultState), \(.defaultCity), \(.zip5)"');
# Do useful things with the completed data set.
echo "${expandedLocationData}, ${fileValue02} ${fileValue03}, ${fileValue04}, ${fileValue05}, ${fileValue06}, ${fileValue07}" > ./DestinationDataFile.csv
done < ./SourceDataFile.csv