我尝试为所有包含值“;从版本”的“描述”键筛选JSON文件,以打印其路径和该值中包含的版本。我用bash脚本来完成所有这些工作。
我要过滤的JSON来自API,并且在不同的路径上具有“ description”键。
这是服务器JSON的摘录
到目前为止,我使用curl来从服务器获取JSON并将其通过以下过滤器传递给jq,以获取包含所有路径的列表,这些路径的描述中包含该值:
curl $api | jq 'paths(objects and (.description|index("; Since version")))'
这将返回一个列表,其中包含指向包含搜索值的端点的路径,如下所示:
[
"paths",
"/v4/user/profileAttributes/{key}",
"delete"
]
[
"paths",
"/v4/users/{user_id}/last_admin_rooms",
"get"
]
[
"definitions",
"GeneralSettings",
"properties",
"s3TagsEnabled"
]
我发现这个filter会返回一个看似随机的键/值对“描述”的值,该值适用于我搜索的字符串而不是整个列表。不幸的是,由于作者没有在其帖子中解释它,所以我对整个过滤器并不十分了解。改编后
curl -s -N $api | jq '. as $in
| reduce paths(type == "string" and test("; Since version")) as $path ({};
($in|getpath($path)) as $x
| if ($path[-1]|type) == "string"
then .[$path[-1]] = $x
else .[$path[-2]|tostring] += [$x]
end )'
返回
{
"description": "Some_Text_We_Dont_Care_About; Since version 4.10.2 Some_More_Text_We_Dont_Care_About"
}
如果第二个过滤器将返回所有条目而不是(接缝随机的)条目,我将能够将两个过滤后的响应缝合在一起。我在此处发布了这两个过滤器,因为也许有人知道如何以一种更简洁的方式进行过滤。
理想情况下,最终结果将返回包含以下条目的列表:
{
"path": "
[
"paths",
"/v4/users/{user_id}/last_admin_rooms",
"get"
]"
",
"version": {
"description": "Some_Text_We_Dont_Care_About; Since version 4.10.2 Some_More_Text_We_Dont_Care_About"
}
}
以下是摘录/示例输入内容:
{
"info": {4 items},
"host": "some_hostname",
"basePath": "/api",
"tags": [19 items],
"paths": {
"/v4/config/info/defaults": {
"get": {
"tags": [
"config"
],
"summary": "Get default values",
"description": "SomeText; Since version 4.6.0 SomeMoreText",
"operationId": "getSystemDefaultsInfo",
"produces": [
"application/json;charset=UTF-8"
],
}
}
"/v4/config/info/general": {
"get": {
"tags": [
"config"
],
"summary": "Get general values",
"description": "SomeText; Since version 4.6.0 SomeMoreText",
"operationId": "getSystemDefaultsInfo",
"produces": [
"application/json;charset=UTF-8"
],
}
}
"definitions": {
"GeneralSettings": {
"type": "object",
"properties": {
"cryptoEnabled": {
"type": "boolean",
"description": "Activation status of encryption"
},
"s3TagsEnabled": {
"type": "boolean",
"description": "Defines if S3 tags are enabled; Since version 4.9.0 NEW"
},
"sharePasswordSmsEnabled": {
"type": "boolean",
"description": "Allow sending of share passwords via SMS"
}
}
}
}
}
答案 0 :(得分:1)
让我为您提供替代解决方案-使用基于步行路径的Unix实用程序 jtc
:
根据您想要的输出,使用jtc
进行查询,
bash $ <file.json jtc -w'[description]:<.*; Since version.*>R: [-1] <act>k [-1] <path>k [-1] <pathname>k' -T'{ "path": [ {{pathname}}, {{path}}, {{act}}], "version": { "description": {{$0}}} }'
{
"path": [
"paths",
"/v4/config/info/defaults",
"get"
],
"version": {
"description": "SomeText; Since version 4.6.0 SomeMoreText"
}
}
{
"path": [
"paths",
"/v4/config/info/general",
"get"
],
"version": {
"description": "SomeText; Since version 4.6.0 SomeMoreText"
}
}
{
"path": [
"GeneralSettings",
"properties",
"s3TagsEnabled"
],
"version": {
"description": "Defines if S3 tags are enabled; Since version 4.9.0 NEW"
}
}
bash $
鉴于您的Json是不规则的(不确定走description
的要求),尽管您是否需要查看最后一个对象也不确定。如果您不需要它,那么知道JSON的结构后,就可以轻松地增强查询以排除像最后一个这样的假阳性匹配。
编辑: 说明:
-T
选项提供了一个Json模板,该模板项(用双花括号{{..}}
括起来)在每次遍历(-w
)结束时从名称空间中插入成功了。
现在,行走路径(-w
)是行走源JSON的方式:jtc
让Json自由地上下行走(使用下标[..]
)并执行递归搜索<..>
。尽管有些项目是directives
-它们不进行任何搜索/匹配,但是它们应用了某些操作(此符号<..>S
中的一个字母后缀定义了它是搜索还是指令)
让我在这里进行分解(顺便说一句,链接中描述了所有词素):
[description]:<.*; Since version.*>R:
-对包含; Since version
的JSON字符串执行RE搜索,但是由于RE拼写匹配整个这样的字符串(请注意RE表达式的开头和结尾处的.*
)。现在,附加标签[description]:
确保仅在具有附加标签的字符串中(而不是其他任何字符串)进行这种RE匹配。 lexeme(又称量词)末尾的:
指示查找所有此类情况(搜索和下标中的量词均与Python表示法兼容)。[-1]<act>k
-[-1]
寻址找到的条目的父节点(来自上一个步骤),<act>k
在名称空间act
中存储条目的标签(以供以后使用)模板插值)-搜索词素末尾的后缀定义是搜索还是指令(在这种情况下,k
是提取标签并存储在名称空间中的指令)[-1]<path>k
将寻址最后找到的条目的父项(在第一步中,该父项又是找到的条目的父项),并将其存储在名称空间中名称为path
下的标签(键)(名称在jtc
中是任意的)[-1]<pathname>k'
-做几乎相同的事情,然后遍历结束(嗯,对于给定的迭代-如果您记得第一个遍历lexeme是迭代的-它找到了每个出现的对象),然后应用了模板插值,从而得到打印的项目。您可以轻松地处理查询(删除每个词位或添加您的词位,查看行走的方式)-我编辑了词位路径,用空格将每个词位打断。
PS>披露:我是jtc
工具的创建者