Suncatcher
Suncatcher

Reputation: 10621

Convert JSON dictionary into Bash one?

I am trying to receive output from an aws-cli command into Bash, and use it as an input to the second. I successfully saved the output into the variable with this helpful answer:

iid=$(aws ec2 run-instances ...)

and receive output like that:

{ "ImageId": "ami-0abcdef1234567890", "InstanceId": "i-1231231230abcdef0", "InstanceType": "t2.micro", ... }

I know that Bash since v4 supports associative arrays but I'm struggling converting one into one.

I tried to parse the dictionary in Bash but received error:

must use subscript when assigning associative array

This is because the right key syntax for Bash dicts is =, not :.

Finally I accessed the members by using this marvelous answer with sed:

echo $iid|sed 's/{//g;s/}//g;s/"//g'|cut -d ':' -f2

My question: is there any standard way of creating a Bash dictionary from JSON or text besides regex? Best-practice?

Considering the snippet from the answer I used, the sed-approach can be very verbose and the verbosity increases exponentially with the number of keys/members:

for items in `echo $db|sed 's/{//;s/}//'`
do
        echo one${count} = `echo $items|sed 's/^.*\[//;s/\].*$//'|cut -d ',' -f1`
        echo two${count} = `echo $items|sed 's/^.*\[//;s/\].*$//'|cut -d ',' -f2`
        echo three${count} = `echo $items|sed 's/^.*\[//;s/\].*$//'|cut -d ',' -f3`
        echo four${count} = `echo $items|sed 's/^.*\[//;s/\].*$//'|cut -d ',' -f4`
        ...
done

For simple dicts it is OK, but for the complex dictionaries with hundreds of keys and a big nesting level it is almost inapplicable.

Is there any unified approach for arbitrary dictionary?

P.S. I found answers about solving the opposite (receiving Bash dict in Python), solving the task through jq, creating dict from Bash to Bash and from non-common input but nothing about specifically JSON. I prefer not to use jq and python and stick to the standard Bash toolset, most of the answers of this collective answer use 3rd-party tools. Is it possible at all?

Upvotes: 1

Views: 1844

Answers (1)

Léa Gris
Léa Gris

Reputation: 19615

One way to turn your JSON object members into a Bash4+'s associative array:

#!/usr/bin/env bash

# shellcheck disable=SC2155 # Associative array declaration from JSON
declare -A assoc=$(
  jq -r '"(",(to_entries | .[] | "["+(.key|@sh)+"]="+(.value|@sh)),")"' \
  input.json
)

# Debug dump the Associative array declaration
typeset -p assoc

Sample output:

declare -A assoc=([InstanceId]="i-1231231230abcdef0" [InstanceType]="t2.micro" [ImageId]="ami-0abcdef1234567890" )

Upvotes: 4

Related Questions