下面是我的curl:的JSON响应示例
{
"success": true,
"message": "jobStatus",
"jobStatus": [
{
"ID": 9,
"status": "Successful"
},
{
"ID": 2,
"status": "Successful"
},
{
"ID": 99,
"status": "Failed"
}
]
}
我想检查ID=2的状态。这是我尝试过的命令:
cat test.txt|jq --arg v "2" '.jobStatus[]|select(.ID == $v)|.status'
响应:没有
我尝试了不带引号的值2
,但仍然没有结果。
相比之下,如果我尝试使用文字2
的命令,它会起作用:
cat test.txt | jq '.jobStatus[]|select(.ID == 2)|.status'
响应:
"Successful"
我被卡住了。有人能帮我找出问题吗?
jq
是数据类型感知:
-
.ID
,如JSON输入中所定义,是数字, -
但是与
--arg
一起传递的任何命令行参数(例如此处的v
)都是字符串,
因此,为了比较它们,您必须使用显式类型转换,例如使用tonumber/1
:
jq --arg v '2' '.jobStatus[] | select(.ID == ($v | tonumber)) | .status' test.txt
假设您在这里只传递标量参数,使用--argjson
(jq
v1.5+)的以下解决方案有点过头了,但它是显式类型转换的替代方案,因为传递JSON参数实际上传递<em]类型的>数据:
jq --argjson v '{ "ID": 2 }' '.jobStatus[] | select(.ID == $v.ID) | .status' test.txt
peak的回答表明,即使--argjson v 2
也能工作(在这种情况下,与$v
相比直接工作),这无疑是最简洁的解决方案,但可能需要解释:
尽管
2
看起来不像JSON,但它是:它是一个有效的JSON文本,包含一个类型为数字的值(请参阅JSON.org)。- 具体来说,
2
是一个以数字开头的未加引号的令牌,这使得它在JSON的上下文中成为一个数字(JSON字符串-值等价于"2"
,它必须作为'"2"'
从shell传递-注意嵌入的双引号)
- 具体来说,
因此,
jq
将--argjson -v 2
解释为数字,比较.ID == $v
按预期工作(请注意,这同样适用于--argjson -v '2'
/--argjson -v "2"
,其中shell在jq
看到值之前删除引号)
相比之下,使用--arg
传递的任何内容始终是按原样使用的字符串值。换言之:
--argjson
的目的是接受任意JSON文本作为字符串(如上例中的'{ "ID": 2 }'
),也可以用于传递数字字符串标量,以强制将其解释为数字
同样的技术也适用于布尔字符串true
和false
。
感谢他的帮助
假设您想检查JSON值2
,您可以选择将--arg的参数转换为数字,或者将--argjson与数字参数一起使用。这些备选方案如下所示:
jq --arg v 2 '.jobStatus[] | select(.ID == ($v|tonumber) | .status'
jq --argjson v 2 '.jobStatus[] | select(.ID == $v) | .status'
请注意,--argjson需要一个相对较新的jq版本。
当然,如果你想"正常化"。ID,使其始终被视为字符串,您可以写:
jq --arg v 2 '.jobStatus[] | select((.ID|tostring) == $v) | .status'