我从curl
获得了一个非常大的JSON流(几GB),并尝试使用jq
处理它。
我想用jq
解析的相关输出被打包在一个表示结果结构的文档中:
{
"results":[
{
"columns": ["n"],
// get this
"data": [
{"row": [{"key1": "row1", "key2": "row1"}], "meta": [{"key": "value"}]},
{"row": [{"key1": "row2", "key2": "row2"}], "meta": [{"key": "value"}]}
// ... millions of rows
]
}
],
"errors": []
}
我想用jq
来提取row
数据,这很简单:
curl XYZ | jq -r -c '.results[0].data[0].row[]'
结果:
{"key1": "row1", "key2": "row1"}
{"key1": "row2", "key2": "row2"}
但是,这始终要等到curl
完成。
我使用了--stream
选项来处理这个问题。我尝试了下面的命令,但它也要等到curl
返回完整的对象:
curl XYZ | jq -n --stream 'fromstream(1|truncate_stream(inputs)) | .[].data[].row[]'
有没有一种方法可以“跳转”到data
字段并开始逐个解析row
,而无需等待结束标记?
3条答案
按热度按时间pgpifvop1#
要获得:
发件人:
执行以下操作(等效于
jq -c '.results[].data[].row[]'
,但使用流):它的作用是:
--stream
).results[].data[].row[]
(带有select(.[0][0] == "results" and .[0][2] == "data" and .[0][4] == "row"
)"results",0,"data",0,"row"
(使用del(.[0][0:5])
)fromstream(1|truncate_stream(…))
模式将生成的jq流转换回预期的JSON例如:
产生所需的输出。
e4yzc0pl2#
(1)您将使用的普通过滤器如下所示:
(2)这里使用流解析器的一种方法是用它来处理
.results[0].data
的输出,但是这两个步骤的组合可能比普通方法要慢。(3)要生成所需的输出,可以运行:
(4)或者,您可以尝试以下方法:
对于说明性输入,来自最后一次调用的输出将是:
["key1","row1"] ["key2","row1"] ["key1","row2"] ["key2","row2"]
aurhwmvo3#
多亏了“JSON Machine"库,有了一个简单且相对快速的解决方案,避免了jq的流解析器(jq --stream)的缺点(*),尽管它需要安装更多的软件。
为了简化使用,我编写了一个名为
jm
的脚本(可以在here中找到),使用这个脚本,只需编写:或者,如果要从.results数组中的所有对象流式传输.data:
(*)主要缺点是缓慢和模糊。