Read JSON arrays into a Bash array

Viewed 333

I have the following json file:

{
  "data": {
    "allPost": {
      "edges": [
        {      
          "node": {
            "slug": "fp-cheat-sheet",
            "labels": [
              "FUNCTIONAL PROGRAMMING",
              "HASKELL",
              "SCALA"
            ]
          }
        },
        {
          "node": {
            "slug": "nlp-101",
            "labels": [
              "DATA SCIENCE",
              "NLP",
              "PYTHON"
            ]
          }
        }
      ]
    }
  }
}

I am writing a shell script to extract info for each edge, using JQ. From each edge, which is an array, I am able to extract slugs which is a string, but not labels which is again an array:

readarray -t slugs < <(cat ${json_file_name} | jq .data.allPost.edges[].node.slug)

readarray -t tags < <(cat ${json_file_name} | jq .data.allPost.edges[].node.labels)

echo ${slugs[1]}
# successfully prints '"nlp-101"'

echo ${tags[1]}
# wrongly prints '"FUNCTIONAL PROGRAMMING",'

I want to extract labels for each post and print it in a file in the exact same format. e.g. for echo ${tags[1]} I want it to print:

 ["DATA SCIENCE", "NLP", "PYTHON"]

How can I fix the above code to extract labels from the above JSON as desired?

2 Answers

Invoke JQ with the -c flag so that it prints each array in a single line.

$ readarray -t tags < <(jq -c '.data.allPost.edges[].node.labels' file)
$ echo "${tags[1]}"
["DATA SCIENCE","NLP","PYTHON"]

Can be done with a single jq call and clever use of ASCII RS delimiter:

#!/usr/bin/env bash

json_file_name=a.json

read -r -d '' jqscript <<JQSCRIPT
.data.allPost.edges[].node.slug + "\u001e",
"\u0000",
(
  .data.allPost.edges[].node.labels | tostring
) + "\u001e"
JQSCRIPT

{
  IFS=$'\x1e' read -r -d '' -a slugs
  IFS=$'\x1e' read -r -d '' -a tags
} < <(
  jq -j "$jqscript" "$json_file_name"
)

declare -p slugs tags

echo "${tags[1]}"
Related