使用 jq 检查字符串是不是是有效的 JSON

Posted

技术标签:

【中文标题】使用 jq 检查字符串是不是是有效的 JSON【英文标题】:Check if string is a valid JSON with jq使用 jq 检查字符串是否是有效的 JSON 【发布时间】:2018-04-07 20:35:37 【问题描述】:

我需要在解除服务时发现错误。响应可以是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 子句结尾。

【问题讨论】:

如果json无效,jq不会报错退出吗? 是的,它给出了一个parse error,但我想知道是否有办法获得简单的10true/false 你可以在返回码中得到它,只需将命令中的 stderr 发送到/dev/null 你是在检查响应是否为json,然后运行其他命令吗?还是您正在检查,然后想对其运行过滤器?有一些方法可以在纯 jq 中做到这一点,但这取决于你在检查它是否为 json 之后想要做什么。 【参考方案1】:

来自手册:

-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 分支。

【讨论】:

哦,对不起,我的错。我需要else 分支,因为我实际上要将此规则封装在while 循环中。因此,如果无法解析 JSON,我需要继续使用 whilejq 命令的否定是什么? 你可以用感叹号来否定它:while ! jq . &gt;/dev/null 2&gt;&amp;1 &lt;&lt;&lt;"$result",或者用until代替while 这不适用于json_string='"omg":"lol"'。根据github.com/stedolan/jq/issues/1539,你应该使用jq type,看看结果是否为空。 @Konrad 感谢分享链接,但在我的 jq (1.5) 版本中,该输入导致 jq .jq type 的输出为空。 我不知道jq . 是否有任何极端情况,所以我个人会选择jq type。两者都返回退出代码0,这是您在 sn-p 中测试的内容。所以对于json_string='"omg":"lol"',你的 sn-p 返回Parsed JSON successfully and got something other than false/null。 (我发现我的评论可能不够清楚:“结果”是指“输出”。)【参考方案2】:

这对我有用

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

返回返回码:

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

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

【讨论】:

如果您愿意,可以稍微巩固一下:./jq -e . &gt;/dev/null 2&gt;&amp;1 &lt;&lt;&lt; "$json_string" 我不太确定。第一次运行可以给你一个空结果,然后重新运行相同的命令给你一个 0。 PIPESTATUS 将为您提供以前的命令管道状态,但不能在当前命令行上工作。 不是| echo $PIPESTATUS[1],使用; echo $PIPESTATUS[1]【参考方案3】:

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

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

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

读作:

使用标志执行jq

-r 输出原始值(无处理或格式化) 如果出现错误,-e 以大于 0 的代码退出 -M 不对 JSON 着色

第一个jq 参数是'""',它输出一个空字符串,有效地防止jq 对用于打印的JSON 进行任何处理

&lt;&lt;&lt; 后跟一个字符串称为“Here String”,基本上是告诉 bash 将该字符串视为文件并将其传递给STDIN(作为命令的输入)。

请注意,您可以将&lt;&lt;&lt;'&lt;MAYBE_INVALID_JSON&gt;' 替换为您要验证的文件的路径,它仍然可以工作

然后将任何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 带有来自原始命令$exit_code 的退出代码的子shell 关闭子shell

【讨论】:

很好,感谢详细的解释!

以上是关于使用 jq 检查字符串是不是是有效的 JSON的主要内容,如果未能解决你的问题,请参考以下文章

如何检查给定字符串是不是是Java中的有效JSON

检查字符串是不是是 Typescript 中的有效 JSON

Java 检查字符串是有效的 JSON 还是有效的 XML,或者两者都不是

我可以将字符串变量传递给 jq 而不是文件吗?

检查响应字符串是 JSON 对象还是 XML?

如何使用jq检查数组中是不是存在元素