Wednesday, February 18, 2015

[jq] Transforming a JSON Object into an Associative Bash Array using jq

JSON is everywhere and playing with API outputs from the command line is getting much more easier since we have jq, the "lightweight and flexible command-line JSON processor"

Here is a small snipet I use to transform some simple JSON into an associative bash array

Lets pretend that we have an api at http://example.com/myapi returning the following output

[
  {
    "service": "one",
    "endpoint": "example.com/service1",
    "timeout": 1,
    "status": "up"
  },
  {
    "service": "two",
    "endpoint": "example.com/service2",
    "timeout": 2,  
    "status": "down"
  },
  {
    "service": "three",
    "endpoint": "example.com/service3",
    "timeout": 3,
    "status": "up"
  }
]
Imagine now that we need to expose this information to some program, we could do something like that :

URL="http://example.com/myapi"

declare -A assoc_array="($(
  curl -sS "${URL}" \
  | jq '.[]  | "[" + .service + "]=\"" +.endpoint + "\""' -r
))"
We now have a populated ${assoc_array} bash array that we can walk like this

for i in ${!assoc_array[@]}; do echo $i ${assoc_array[$i]}; done
Using jq we could even filter out the services that  are "down"

declare -A assoc_array="($(
  curl -sS "${URL}" \
  | jq '.[] | select(.status == "up") | "[" + .service + "]=\"" +.endpoint + "\""' -r
))"
Imagine now that we need to export as many environment variables as services present in the API output; We could do :

URL="http://example.com/myapi"

declare -A assoc_array="($(
  curl -sS "${URL}" \
  | jq '.[]  | "[" + .service + "]=\"" +.endpoint + "\""' -r
))"

for key in ${!assoc_array[@]}; do 
  sanitizedKey=${key/-/_};
  eval ZBO_${sanitizedKey^^}='$(echo ${assoc_array[$key]})';
done

Happy JSONing !!

No comments: