【问题标题】:Use JQ to select specific, arbitrarily nested objects from JSON使用 JQ 从 JSON 中选择特定的、任意嵌套的对象
【发布时间】:2018-06-02 03:14:07
【问题描述】:

我正在寻找有效的方法来在大型 JSON 对象中搜索与过滤器匹配的“子对象”(我想是通过 select())。然而,顶级 JSON 是一个包含任意嵌套的对象,包括更简单的值、对象和对象数组。例如:

{
  "name": "foo",
  "class": "system",
  "description": "top-level-thing",
  "configuration": {
    "status": "normal",
    "uuid": "id"
  },
  "children": [
    {
      "id": "c1",
      "class": "c1",
      "children": [
        {
          "id": "c1.1",
          "class": "c1.1"
        },
        {
          "id": "c1.1",
          "class": "FINDME"
        }
      ]
    },
    {
      "id": "c2",
      "class": "FINDME"
    }
  ],
  "thing": {
    "id": "c3",
    "class": "FINDME"
  }
}    

我有一个解决方案部分我想要(并且是可以理解的):

jq -r '.. | arrays | .[] | select(.class=="FINDME"?) | .id'

返回:

c2
c1.1

...然而,它错过了c3,而且它改变了项目输出的顺序。此外,我希望这可以在可能非常大的 JSON 结构上运行,我想确保找到一个有效的解决方案。 jq 新手(包括我自己)仍然可以阅读的内容的奖励积分。

FWIW,我在路上用来帮助我的参考资料,以防他们帮助别人:

【问题讨论】:

    标签: json object select nested jq


    【解决方案1】:

    对于小到中等大小的 JSON 输入,.. 是正确的方向 但您似乎想选择objects,如下所示:

    .. | objects | select(.class=="FINDME"?) | .id
    

    对于非常大的 JSON 文档,这可能需要太多内存,因此可能值得了解 jq 的流解析器。不幸的是,它使用起来要困难得多,所以我建议尝试上述方法,如果您有兴趣,请在通常的地方查找有关 --stream 选项的文档。

    【讨论】:

    • 嗯,这应该很明显 - 我将使用此选项,直到遇到性能问题。
    【解决方案2】:

    这是一个流解析器解决方案。要理解它,您需要阅读 --stream 选项,但关键是输出包含以下形式的行:[PATH, VALUE]

    program.jq

    foreach inputs as $in (null;
      if has("id") and has("class") then null
      else . as $x
      | $in
      | if length != 2 then null
        elif .[0][-1] == "id" then ($x + {id: .[-1]})
        elif .[0][-1] == "class"
             and .[-1] == "FINDME" then  ($x + {class: .[-1]})
        else $x
        end
      end;
      select(has("id") and has("class")) | .id )
    

    调用

    jq -n --stream -f program.jq input.json
    

    带有样本输入的输出

    "c1.1"
    "c2"
    "c3"
    

    【讨论】:

    • 虽然比您给出的其他答案可读性差,但它可以满足我的要求。包括保留订单,我会从它的使用中学到一些东西。谢谢。
    • 请注意更新以删除假设。发布一些有关您的文件大小和比较时间的详细信息如何?
    • 感谢您删除更新的假设。由于输出可能与我的示例略有不同,因此这一点很有帮助。至于时间,我还没有真正的数据集,所以我不能提供。我可能会生成一些模拟数据集,如果我这样做了,我会发布一个比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2023-01-09
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多