使用 jq --stream 获取 JSON 对象的值

Get value of JSON object using jq --stream

我正在尝试使用 jq --stream 提取 JSON 对象的值,因为真实数据的大小可以达到数 GB。

这是我用于测试的 JSON,我想在其中提取 item 的值:

{
  "other": "content here",
  "item": {
    "A": {
      "B": "C"
    }
  },
  "test": "test"
}

我正在使用的 jq 选项:

jq --stream --null-input 'fromstream(inputs | select(.[0][0] == "item"))[]' example.json

但是,这个命令没有得到任何输出。

我发现一件奇怪的事情是,在 item 之后删除对象时,上面的命令似乎有效:

{
  "other": "content here",
  "item": {
    "A": {
      "B": "C"
    }
  }
}

结果符合预期:

❯ jq --stream --null-input 'fromstream(inputs | select(.[0][0] == "item"))[]' example.json
{
  "A": {
    "B": "C"
  }
}

但由于我无法控制输入 JSON 这不是解决方案。

我在 MacOS 上使用 jq 1.6 版。

您没有截断流,因此在将其过滤为仅包含 .item 以下的部分后,fromstream 缺少最后的 back-tracking 项 [["item"]]。要么在最后手动添加它(不推荐,这也会在结果中包含 top-level 对象),或者更简单,使用 1 | truncate_stream 完全去除第一层:

jq --stream --null-input '
  fromstream(1 | truncate_stream(inputs | select(.[0][0] == "item")))
' example.json
{
  "A": {
    "B": "C"
  }
}

或者,您可以使用 reducesetpath 自己构建结果对象:

jq --stream --null-input '
  reduce inputs as $in (null;
    if $in | .[0][0] == "item" and has(1) then setpath($in[0];$in[1]) else . end
  )
' example.json
{
  "item": {
    "A": {
      "B": "C"
    }
  }
}

要删除顶级对象,请在末尾过滤 .item,或者类似于 truncate_stream,使用 [1:] 删除路径的第一项以去除第一级:

jq --stream --null-input '
  reduce inputs as $in (null;
    if $in | .[0][0] == "item" and has(1) then setpath($in[0][1:];$in[1]) else . end
  )
' example.json
{
  "A": {
    "B": "C"
  }
}