save json jq output as seperate variables or as an array

129 Views Asked by At

I am currently working with i3 and would like to parse the visible workspaces with i3-msg -t get_workspaces, to "save the workspace" and return to them when my pomodoro break is over, problem is I've never worked with json in bash before (aside from a couple quick examples maybe an hour ago). basically I am trying to return the name value of the visible workspaces.

[
  {
    "id": 94475011596992,
    "num": 6,
    "name": "6:NoteTaking",
    "visible": false,
    "focused": false,
    "rect": {
      "x": 40,
      "y": 65,
      "width": 1840,
      "height": 975
    },
    "output": "DisplayPort-2",
    "urgent": false
  },
  {
    "id": 94475011603104,
    "num": 7,
    "name": "7:Entertainment",
    "visible": false,
    "focused": false,
    "rect": {
      "x": 40,
      "y": 65,
      "width": 1840,
      "height": 975
    },
    "output": "DisplayPort-2",
    "urgent": false
  },
  {
    "id": 94475011612464,
    "num": 9,
    "name": "9",
    "visible": true,
    "focused": true,
    "rect": {
      "x": 40,
      "y": 65,
      "width": 1840,
      "height": 975
    },
    "output": "DisplayPort-2",
    "urgent": false
  },
  {
    "id": 94475011631328,
    "num": 1,
    "name": "1:Browsing",
    "visible": true,
    "focused": false,
    "rect": {
      "x": 40,
      "y": 1145,
      "width": 1840,
      "height": 975
    },
    "output": "DisplayPort-1",
    "urgent": false
  },
  {
    "id": 94475011637712,
    "num": 2,
    "name": "2:Messaging",
    "visible": false,
    "focused": false,
    "rect": {
      "x": 40,
      "y": 1145,
      "width": 1840,
      "height": 975
    },
    "output": "DisplayPort-1",
    "urgent": false
  },
  {
    "id": 94475011644096,
    "num": 3,
    "name": "3",
    "visible": false,
    "focused": false,
    "rect": {
      "x": 40,
      "y": 1145,
      "width": 1840,
      "height": 975
    },
    "output": "DisplayPort-1",
    "urgent": false
  }
]

Currently I have this line doing most of the heavy lifting,

  local currentWorkspaces=$(i3-msg -t get_workspaces | jq -r 'map(select(.visible == true)).name')

it's returning the right values (granted they are in quotes.)

[
  "9",
  "1:Browsing"
]

I've been trying to call them with a simple array (never worked with arrays either so might be messing stuff up) i3-msg workspace "$currentWorkspaces[@]"

currently I have no idea how to move forward, and any help would be appreciated (-r the option I thought would return the values without quotes isn't doing so)

2

There are 2 best solutions below

6
peak On BEST ANSWER

Assuming the values in .name have no spaces or certain other characters, you would be able to get away with something along the lines of the following:

X=($(i3-msg -t get_workspaces | jq -r '.[] | select(.visible == true).name' ))

for var in "${X[@]}"
do
  echo "$var"
done 

Output:

9
1:Browsing

More robustly, if your shell has readarray:

readarray -t X < <(... | jq -r '.[] | select(.visible == true).name ')

Otherwise, you could use the idiom:

vars=(); while IFS= read -r line; do vars+=("$line"); done < .....
0
pmf On

the ideal solution would be to have it stored in a array

Assuming you mean a bash array, you can use declare to declare it, and use jq's @sh to properly escape the contents.

For an indexed array, use declare -a:

$ declare -a cw="($(i3-msg … | jq -r '.[]  | select(.visible).name | @sh'))"

$ declare -p cw  # print for testing
declare -a cw=([0]="9" [1]="1:Browsing")

For an associative array, use declare -A, and output each keys before its value:

$ declare -A cw="($(i3-msg … | jq -r '.[]  | select(.visible) | .output, .name | @sh'))"

$ declare -p cw  # print for testing
declare -A cw=([DisplayPort-2]="9" [DisplayPort-1]="1:Browsing" )