2

The question is exactly the opposite of Constructing a json hash from a bash associative array. Given the following JSON:

{
    "a": "z",
    "b": "y",
    "c": "x"
}

I would like to have an associative Bash array.

0

2 Answers 2

4

A NUL-delimited stream is the safest approach:

input='{"a":"z","b":"y","c":"x"}'
declare -A data=()

while IFS= read -r -d '' key && IFS= read -r -d '' value; do
    data[$key]=$value
done < <(jq -j 'to_entries[] | (.key, "\u0000", .value, "\u0000")' <<<"$input")

Note the use of jq -j, which suppresses quoting (like -r), but also suppresses the implicit newline between items, letting us manually insert a NUL instead.

See the discussion in https://github.com/stedolan/jq/issues/1271 (a ticket explicitly requesting a NUL-delimited output mode), wherein this idiom was first suggested.

Sign up to request clarification or add additional context in comments.

Comments

-4

You can do it like this :

while IFS=':' read k v 
do 
    dict[$k]="$v"
done <<< "$( sed -E "s/(\"|,|{|})//g; /^ *$/d; s/^ *//g" input.txt )"

echo "The value of key 'a' is : ${dict[a]}"

Hope it helps you!

5 Comments

This works only for JSON formatted exactly as originally given, and only with a sed having the non-POSIX-defined -E argument. Your JSON has more than one key/value pair on a single line? Won't work. Your JSON has spaces inside the key names or values? Won't work. Your JSON has backslash-escaped literal quotes? Won't work. Your JSON has literal {s inside of the strings? They disappear. Etc.
Yeah. I know. But all of those cases are not the input given in the question. As far as the given input is what shown, it will work.
If the OP only wanted something that worked for the specific input in the question, then you could just answer declare -A dict=( [a]="z" [b]="y" [c]="x" ). Obviously that's useless/absurd; an answer needs to be good generally, not only for the single sample input.
This discussion could go on forever and I know my answer would work only for his very specific use case. But for what he is trying to achieve I can imagine he has a very simple goal in mind, otherwise why would you do this using Bash and JQ? Why does he want to use totally inappropriate tools for the task? Because OP surely just wants a quick and dirty solution to solve a specific task and move on to something else. If he really wanted a solid way to handle json data he would be using some programming language and not command line magic to begin with.
A bash associative array can handle any map[string]string, so long as both the keys and values are C strings (which is to say, containing no NULs). jq, similarly, can handle any valid JSON -- it's a quite powerful programming language in its own right, and for that matter considerably more powerful than bash insofar as nested data structure manipulation is called for. Which is to say -- there are domain limitations implied by the tools selected, sure; but that's not a reason or excuse for adding your own arbitrary limitations on top, especially without disclosing them.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.