用jq嵌套过滤

时间:2019-01-18 13:24:37

标签: json shell select command-line jq

我是jq的第一次用户,我想根据对象中的值过滤掉对象,而我正努力弄清楚它。

我有一个很大的json文件,其中包含很多产品数据,如下所示。我想根据它们具有哪些website_id进行过滤。

示例输入:

ItemsControl

所需的输出:

[{
    "product_id": "2",
    "sku": "PROD2",
    "name": "Product Name 2",
    "set": "4",
    "type": "simple",
    "category_ids": {
      "item": "15"
    },
    "website_ids": {
      "item": [
      "1",
      "4"
    ]}
},{
    "product_id": "3",
    "sku": "PROD3",
    "name": "Product Name 3",
    "set": "4",
    "type": "simple",
    "category_ids": {
      "item": "15"
    },
    "website_ids": {
      "item": [
      "1",
      "2"
    ]}
}]

我尝试了几种不同的方法,但是显然我没有理解。

[{ "product_id": "2", "sku": "PROD2", "name": "Product Name 2", "set": "4", "type": "simple", "category_ids": { "item": "15" }, "website_ids": { "item": [ "1", "4" ]} }]

给我:

jq 'map(.website_ids.item[] | contains("4"))'

似乎与我想要的website_ids项匹配,但我不确定如何从中获取完整的JSON对象。

任何帮助将不胜感激!谢谢。

编辑:

我已经使用了它,并且可以用于我的示例:

[ false, true, false, false ]

我意识到我的示例和我实际测试的文件存在一些差异。

有时某个产品的website_id项具有以下内容:

“网站ID”:{       “项目”:“ 2”    }

哪个会导致错误:

map(select(.website_ids.item[] | contains("4")))

有没有办法解决这个问题?

1 个答案:

答案 0 :(得分:1)

您需要做的就是在地图函数中添加一个select调用,如下所示:

jq 'map(select(.website_ids.item[] | contains("4")))'

编辑后,它有点复杂,但是可以通过检查.website_ids.item的类型,然后根据该类型进行包含检查或简单的相等性检查来解决:

map((select((.website_ids.item | type) == "array") | select(.website_ids.item[] | contains("4"))), (select((.website_ids.item | type) == "string") | select (.website_ids.item == "4")))

这里的格式更具可读性:

map(
    (select((.website_ids.item | type) == "array") | select(.website_ids.item[] | contains("4"))),
    (select((.website_ids.item | type) == "string") | select (.website_ids.item == "4"))
)