使用jq

时间:2017-10-26 12:43:35

标签: json bash jq

提升服务时我需要发现错误。响应可以是null,这是一个字符串错误消息,如

error services-migration/foobar: Not found: services-migration/foobar

当一切都很好时,

或有效的JSON。我想知道是否有jq方法可以简单地检查提供的字符串是否是有效的JSON。我可以检查字符串中的某些关键字,例如error f.e.,但我正在寻找一个更强大的选项,例如。我从jq获得了true/false1/0。 我正在查看jq的文档以及有关SO的一些问题,但所有内容都是关于从JSON中查找和选择键值,而不是简单地验证字符串。

更新:

我有这个:

 result=$(some command)

结果是字符串error services-migration/foobar: Not found: services-migration/foobar

然后是if语句:

 if jq -e . >/dev/null 2>&1 <<<"$result"; then
    echo "it catches it"
 else
    echo "it doesn't catch it"
 fi

它始终以else子句结束。

3 个答案:

答案 0 :(得分:18)

从手册:

  

-e / --exit-status:

     

如果最后一个输出值既不是false也不是null,则将jq的退出状态设置为0;如果最后一个输出值为false或null,则设置为1;如果没有生成有效结果,则设置为4。通常,如果有任何使用问题或系统错误,jq将退出2;如果存在jq程序编译错误,则退出3;如果运行jq程序,则退出0。

所以你可以使用:

if jq -e . >/dev/null 2>&1 <<<"$json_string"; then
    echo "Parsed JSON successfully and got something other than false/null"
else
    echo "Failed to parse JSON, or got false/null"
fi

事实上,如果您不在乎区分不同类型的错误,那么您可能会失去-e开关。在这种情况下,过滤器.将成功解析任何被认为是有效JSON(包括false / null)的任何内容,程序将成功终止,因此将遵循if分支。

答案 1 :(得分:8)

这对我有用

echo $json_string | ./jq -e . >/dev/null 2>&1  | echo ${PIPESTATUS[1]}

返回返回码:

  • 0 - 成功
  • 1 - 失败
  • 4 - 无效

然后您可以通过进一步的代码评估返回代码。

答案 2 :(得分:1)

下面的命令和解释尝试以最便宜的方式使用 jq,就像验证 JSON 的方法一样。在我看来,有一些工具更适合于此(例如 JSONLint),但如果您手头只有 jq,那么这就是我的贡献。

要验证 JSON 文件并仍然使用 STDERR 获取 jq 输出中的错误,您可以使用以下 bash one-liner

jq -reM '""' <<<'<MAYBE_INVALID_JSON>' 1>/dev/null

内容如下:

  • 使用标志执行 jq

    • -r 输出原始值(无处理或格式化)
    • -e 以大于 0 的代码退出,如果出现错误
    • -M 不对 JSON 着色
  • 第一个 jq 参数是 '""',它输出一个空字符串,有效防止 jq 对 JSON 进行任何处理以进行打印

  • <<< 后跟一个字符串称为“此处字符串”,基本上是告诉 bash 将字符串视为文件并将其传递给 STDIN (作为输入到命令)。

    请注意,您可以将 <<<'<MAYBE_INVALID_JSON>' 替换为要验证的文件的路径,它仍然有效

  • 然后将任何 STDOUT 输出(通常包含 JSON)重定向到 /dev/null,有效地丢弃它

您还可以通过使用以下命令来获得更好的效果并在错误下方输出自定义消息:

jq -reM '""' <<<'<MAYBE_INVALID_JSON>' 1>/dev/null || ( exit_code="$?"; echo 'ERROR: Invalid JSON file. See errors above' 1>&2; exit "$exit_code" )

其中添加的部分如下:

  • || 表示:如果前一个命令失败并返回非零退出代码,则运行以下命令
  • 使用 ( 打开子 shell。这实际上是需要的,因为我们想使用原始命令的退出代码退出
    • exit_code 环境变量设置为最后一条命令的退出代码 $?
    • 使用 echo 打印自定义错误消息
    • exit 带有原始命令退出代码的子 shell $exit_code
  • 关闭子shell