一个“只会查 JSON”的小工具,为何敢叫板 jq?jsongrep 想把路径搜索做成 JSON 世界的 ripgrep

开发工具 2026年3月27日
Rust 新工具 jsongrep 最近放出了一篇很有攻击性的技术文章:它声称自己在 JSON 路径搜索上,比 jq、jmespath、jsonpath-rust 和 jql 都更快。真正有意思的并不只是“更快”这件事,而是它把 JSON 查询重新定义成“树上的正则匹配”,再用 DFA 一次遍历解决问题——这让人看到了命令行数据工具另一种可能的进化方向。

当 JSON 也开始需要一个“ripgrep”

命令行世界里,grep 是老朋友,ripgrep 则像那个后来居上的年轻人:更快、更聪明、默认更现代。现在,JSON 这个早已无处不在的数据格式,也有人试图复制这条路线。

开发者 Micah Kepe 最近介绍了自己打造的 Rust 工具 jsongrep。它的野心写在标题里:在 JSON 路径查询这件事上,它比 jqjmespathjsonpath-rustjql 都更快。这样的标题很容易让人下意识挑眉——毕竟 jq 在很多工程师心里几乎已经是 JSON 的“瑞士军刀”,功能多、生态成熟、心智占领彻底。一个新工具要公开“叫板”,不是没有勇气,就是确实有点东西。

从产品定位看,jsongrep 并不打算成为下一个 jq。它不做复杂变换,不负责算术、不负责过滤器链式魔法,也不想去接管你的整个 JSON 工作流。它盯上的只是一个极其具体、却又极其常见的场景:在一大坨 JSON 里快速找到路径匹配的值。这个切口很小,但恰恰因为小,才有机会做到极致。

如果你经常和日志、API 返回、配置快照、云平台导出的结构化数据打交道,你会明白这件事为什么不无聊。很多时候,我们并不是想“改写 JSON”,只是想赶紧知道:某个字段到底出现在哪、嵌套多深、哪些对象里有这个键、数组里哪个元素满足路径模式。jq 当然能做,但它更像一把军刀;jsongrep 想做的是一把专门削苹果的小刀,最好又快又顺手。

它快,不只是因为 Rust,而是因为“换了问题的问法”

jsongrep 最值得聊的地方,不在于它是 Rust 写的——如今性能工具用 Rust 并不稀奇——而在于它对 JSON 查询的理解方式。作者的核心观点很漂亮:JSON 文档本质上是一棵树,而查询其实是在描述这棵树上的路径。

一旦接受这个视角,事情就有意思了。传统的 JSON 查询工具,很多是在“解释执行”路径表达式:走到一个节点,判断一下表达式;要是有递归下降、分支匹配、过滤条件,就继续往下试。这个过程像边走边想,灵活,但也容易反复回头,尤其在文档很大、查询很多、路径又复杂的时候,性能压力会迅速放大。

jsongrep 则换了一种思路:把查询语言当成一种正则语言。只不过,正则匹配的不再是字符串里的字符,而是 JSON 树上的“边”——对象键名、数组索引、通配符、范围等等。既然是正则语言,就能被编译成自动机;既然能编译成自动机,就能在遍历 JSON 时按状态机一路往前走。说白了,它不是一边搜索一边琢磨“这句查询到底是什么意思”,而是先把查询预编译好,再拿着一台已经调好的机器去扫整棵树。

这也是它敢谈速度的底气所在。DFA,也就是确定型有限自动机,最迷人的地方就是“每读一个符号,做一次确定的状态转移”。没有回溯,没有递归爆炸,也少了很多解释器层面的额外开销。对熟悉文本搜索工具的人来说,这种思路会让人自然想到 ripgrep 乃至更早的正则引擎优化传统。Micah Kepe 在文章里也直接承认,这个项目的灵感就是向 Andrew Gallant 的 ripgrep 致敬。

这件事的重要性,在于它提醒了整个开发者工具圈:性能突破有时不来自更猛的硬件,也不来自微优化,而来自重新定义问题。 你把 JSON 查询看成“表达式解释”,和把它看成“树路径上的正规语言匹配”,最后会得到两类完全不同的系统。

从“查字段”到“走树”,这门小 DSL 其实挺聪明

别看 jsongrep 这个名字朴素,它的查询语法并不粗糙。字段访问、数组索引、数组通配、分支选择、可选匹配、Kleene 星号这样的重复匹配,它都支持。比如你想找任意深度下所有叫 name 的字段,可以用类似 ( | [])*.name 的写法;如果懒得写,它还提供了一个 -F 选项,直接把字段名当作递归搜索目标。这种设计很务实,照顾了“懂原理的人”,也照顾了“我就想赶紧查出来”的普通用户。

有趣的是,作者并没有回避它的短板,反而专门写了一个“anti-pitch”。翻译成人话大概就是:别把我当 jq 替代品,我没那么全能;我现在也没那么普及;而且项目还新,别急着把生产系统全押上来。这种坦率在开发者工具里很加分,因为它没有陷入那种“我什么都能做”的产品幻觉。

我个人很认同这种定位克制。过去几年,命令行工具里最成功的新项目,往往不是“取代一切”的大而全,而是“把一个高频动作做到极好”的小而锋利。fd 对标 findbat 对标 catrg 对标 grep,背后都是同一个逻辑:老工具不是不行,而是它们背着历史包袱;新工具靠更清晰的边界和更现代的实现,专门赢下某一个环节。

jsongrep 现在显然也在走这条路。它真正的挑战不是技术,而是用户习惯。工程师已经太习惯在 shell 里敲 jq 了,很多人甚至会把所有 JSON 问题都先翻译成 jqjsongrep 要说服大家,必须让用户在几个真实场景里明显感受到:哦,原来“查路径”这件事,真能快到像 grep 那样自然。

真正的看点,在自动机理论终于落地成了手感

文章里最“硬核”的部分,是作者详细解释了自己的引擎:先把查询解析成 AST,再用 Glushkov 算法构建无 epsilon 的 NFA,然后通过子集构造法转成 DFA,最后在遍历 JSON 树时做状态转移。对很多读者来说,这串词看起来像编译原理老师突然闯进了终端窗口;但换个角度,这恰恰是整件事最迷人的地方。

因为这不是“为了学术而学术”,而是很罕见地把课堂里的自动机理论,做成了一个你真能在命令行里安装、真能拿来查日志的工具。一个简单查询,比如 roommates[*].name,在 jsongrep 眼里不是什么“解释器脚本”,而是一串可被编号、可计算 First/Last/Follows 集合、可编译成状态图的符号。最终扫描 JSON 时,它就是在树上做一次深度遍历,同时驱动自动机前进。

这类设计最让人兴奋的一点,是它通常具备很强的可扩展性。今天它支持字段、索引、范围、通配、可选和重复,明天如果要继续扩展,只要不破坏“正规语言”这层边界,整套编译思路依然成立。反过来说,这也是它天然的限制:一旦用户开始要求复杂过滤谓词、数值比较、上下文相关判断,它就会逐渐远离“正规语言”的舒适区,性能和表达力之间的平衡也会变得棘手。

这背后其实是一个老问题:开发者到底更需要“什么都能做”,还是“把常见动作做到近乎零成本”? jq 代表前者,jsongrep 暂时选择了后者。技术史反复证明,这两类工具不会互相消灭,反而常常共存。你写复杂数据变换时还是会回到 jq,但当你只是想在 190MB 的 JSON 文件里秒找所有匹配路径,新的专用工具就有了存在价值。

基准测试很亮眼,但这场比赛还没结束

作者在文章里花了很大篇幅谈基准测试,比较了解析时间、查询编译时间、搜索时间以及端到端总时间。按照他的结果,jsongrep 在大型数据集上的路径搜索表现非常激进,尤其是端到端性能图,很有那种“既然你都把图画出来了,摆明就是来砸场子的”味道。

不过,作为看过太多性能宣言的记者,我对这类结论向来有两层反应。第一层是:这确实值得兴奋,因为作者至少认真讨论了公平性、等价查询和测试方法,没有只拿最有利的场景做海报。第二层是:所有 benchmark 都有上下文。不同工具的设计目标不同,jq 并不是为纯路径搜索而生;它还承担变换、选择、组合和表达力的任务。拿一辆越野车去比赛道单圈,不代表越野车失败了,只能说明赛道车在赛道上更快。

真正值得观察的是,jsongrep 能不能把这种“基准优势”转化成开发者日常工作流里的真实优势。比如它是否容易嵌入 shell pipeline,是否能稳定处理脏数据,错误信息是否足够友好,跨平台体验是否一致,面对超深嵌套或怪异键名时是否依旧可靠。这些问题没有性能图那么耀眼,却决定了一个命令行工具能不能活过“GitHub 热门项目”的那几天。

还有一个更现实的问题:当越来越多 AI 代理、自动化脚本和 observability 工具开始吞吐海量 JSON 时,我们是不是需要更多“专门为搜索优化”的数据工具,而不是把所有任务都塞给通用解释器?我倾向于认为答案是肯定的。过去的 JSON 工具更多是“人用”;未来的 JSON 工具,很多其实是“人和机器一起用”。在这种背景下,快、稳定、可组合,重要性会进一步上升。

如果说 jq 代表了 JSON 时代的第一阶段——强表达力优先,那么 jsongrep 可能代表了第二阶段的一个信号:在海量结构化数据面前,查询工具也开始分化,朝专用化、高性能和编译化演进。 这不意味着旧王退位,但新选手确实已经进场了。

Summary: 我对 `jsongrep` 的判断是:它未必会取代 `jq`,但很可能会在“JSON 搜索”这个子领域站稳脚跟。它最有价值的地方,不是跑分赢了谁,而是证明了把 JSON 路径查询编译成自动机这条路是可行的,而且有实战意义。接下来如果它能补齐生态、稳定性和真实工作流集成,未来开发者的终端里,大概率会像同时装 `grep` 和 `ripgrep` 一样,同时装着 `jq` 和 `jsongrep`。
jsongrepJSON 路径搜索jqRustDFA树上的正则匹配命令行数据工具ripgrepjmespath性能优化