仅当它是 JSON 时才通过 jq 管道输出

P i*_*P i 1 bash curl conditional-statements jq

我有以下 BASH 代码:

    response=$( curl -Ls $endpoint )
    if [ -n "$response" ]; then  # nonempty
        echo "$response"  | jq .
    fi
Run Code Online (Sandbox Code Playgroud)

问题是有时响应可以是非空的,但不是 JSON(如果它不是 200)。

jq如果输出是有效的 JSON,是否可以通过管道传输输出?

以下工作:

echo $x | jq . 2>/dev/null  || echo $x
Run Code Online (Sandbox Code Playgroud)

测试:

> x='{"foo":123}'; echo $x | jq . 2>/dev/null || echo "Invalid: $x"
{
  "foo": 123
}

> x='}'; echo $x | jq . 2>/dev/null || echo "Invalid: $x"
Invalid: }
Run Code Online (Sandbox Code Playgroud)

但是,我对此感到不舒服。

Léa*_*ris 6

如果您想在将其提交到 之前测试响应类型jq,则可以测试Content-Type来自服务器响应的标头。

所以你想curl向你发送完整的响应头和正文curl -i

这是它的一个实现:

#!/usr/bin/env sh

endpoint='https://worldtimeapi.org/api/timezone/Europe/Paris.json'

# Headers and body are delimited by an empty line, with CRLF as the line ending.
# See: RFC7230 HTTP/1.1 Message Syntax and Routing / section 3: Message Format
# https://tools.ietf.org/html/rfc7230#section-3
crlf="$(printf '\r\n_')" # add trailing _ to prevent trailing newline trim
crlf="${crlf%_}" # remove trailing _
http_delim="$crlf$crlf" # RFC7230 section 3

full_http_response="$(curl --silent --include --url "$endpoint")"
http_headers="${full_http_response%$http_delim*}"
http_body="${full_http_response#*$http_delim}"

case $http_headers in
  'HTTP/1.1 200 OK'*'Content-Type: application/json'*)
    # Yes, response body is JSON, so process it with jq.
    jq -n "$http_body"
    ;;
esac
Run Code Online (Sandbox Code Playgroud)