As jesse_b pointed out, the issue is that your array is not an associative array. The bash on macOS doesn't know how to deal with associative arrays, so consider rewriting it in zsh or use ordinary arrays.
The following will work with the default bash on macOS, assuming jq is also installed:
menu_select_server () { local server_json=file.json # JSON containing server config # Set positional parameters to list of servers eval "$( jq -r '[ "set --", (.[].name|@sh) ] | @tsv' "$server_json" )" # Select wanted server local PS3='Select server: ' select SELECTED_SERVER; do [[ -n $SELECTED_SERVER ]] && break done # Get corresponding hash SELECTED_HASH=$( jq -r --argjson i "$REPLY" \ '.[($i-1)].hash' "$server_json" ) } We parse the file twice here, once to get the list of servers, and once to get the hash for the selected server, but it would be easy to do something similar to what you're doing and just switch to using $REPLY coming out from the select loop to get the hash:
menu_select_server () { local server_json=file.json # JSON containing server config local name hash local hashes=() set -- # Read names into list of positional parameters # Read hashes into "hashes" array while IFS=$'\t' read -r name hash; do set -- "$@" "$name" hashes+=( "$hash" ) done < <( jq -r '.[] | [ .name, .hash ] | @tsv' "$server_json" ) # Select wanted server local PS3='Select server: ' select SELECTED_SERVER; do [[ -n $SELECTED_SERVER ]] && break done # Get corresponding hash SELECTED_HASH=${hashes[REPLY-1]} }