skip to Main Content

I am doing a curl call to a server from a bash script. In the response I want to extract some data using jq. but, I am getting below error from jq

jq: error (at <stdin>:1): Cannot index number with string "_links"

Part of script:

#!/bin/bash

set -e

keyword="config"

response=$(curl --location "${HEADERS[@]}" -s -w "%{http_code}n" -X GET "$url")

if echo ${response} | grep "$keyword" ; then
    extract=$(jq -r "._links" <<< "${response}")
    echo "$extract"
fi

The actual response:

{
    "config": {
        "polling": {
            "sleep": "00:20:00"
        }
    },
    "_links": {
        "deployment": {
            "href": "https://www.example.com"
        },
        "configData": {
            "href": "https://www.example.com/configData"
        }
    }
}
200

Can anyone please let me know what is the issue here?

Thanks in advance

P.S: I am testing on Ubuntu (on WSL). please let me know if any info is missing

2

Answers


  1. Your variable response does not contain what you have shown. The actual content of the variable is:

    {
        "config": {
            "polling": {
                "sleep": "00:20:00"
            }
        },
        "_links": {
            "deployment": {
                "href": "https://www.example.com"
            },
            "configData": {
                "href": "https://www.example.com/configData"
            }
        }
    }
    200
    

    That 200 is added to the output because you call curl -w "%{http_code}n", which will add the response status code to the output. If you plan on processing the output, get rid of the -w option (you are not parsing it with jq, so you don’t need it).

    If you require 200 to be part of the output, then you could instruct jq to read the full input into a single array and only operate on the first item:

    jq -s 'first._link' <<< "$response"
    

    But in that case, I recommend going with Charles Duffy’s answer and use -n in combination with input.

    Login or Signup to reply.
  2. If your input has a JSON document followed by other content, you can make your jq only read that one input:

    extract=$(jq -n "input | ._links" <<<"$response")
    

    The -n tells jq not to read anything by default; the -n, used exactly once, tells it to read one thing.


    You could also extract both the _links attribute and the HTTP status code with just one invocation of jq:

    IFS=$'n' read -r -d '' extract http_code < <(
      jq -nc '
        input as $full_doc | input as $status_code |
        (($full_doc | ._links), $status_code)
      ' <<<"$response" && printf ''
    )
    

    Using read -d '' causes read to fail if it doesn’t find a NUL at the end of input, and the && printf '' adds a NUL at the end of the process substitution‘s output if jq reports success.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search