news 2026/8/25 10:03:53

如何用OCaml实现一个JSON查询语言?query-json架构解析:从词法分析到解释执行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何用OCaml实现一个JSON查询语言?query-json架构解析:从词法分析到解释执行

如何用OCaml实现一个JSON查询语言?query-json架构解析:从词法分析到解释执行

【免费下载链接】query-jsonFaster, simpler and more portable implementation of jq-inspired language in OCaml项目地址: https://gitcode.com/gh_mirrors/qu/query-json

query-json是用 OCaml 实现的一款快速、简洁且可移植的JSON 查询语言,可以理解为「更快更好用的 jq」:它把一条 JSON 查询语句经过词法分析 → 语法解析 → 抽象语法树(AST)→ 解释执行四个阶段,最终输出查询结果。本文面向新手,不堆砌代码,带你完整拆解这套 JSON 查询引擎的架构设计。

🗂️ 总体架构:一条查询的旅程

当你输入query-json '.store.books[0].title' bookstore.json时,项目内部的Core.ml模块会编排一次完整流水线:

阶段负责模块作用
① 词法分析source/Lexer.ml把查询文本切分成 token 流
② 语法分析source/Parser.ml把 token 组装成语法树
③ AST 表示source/Ast.ml定义表达式、函数、运算符等数据结构
④ 函数库source/Language.ml管理所有内置函数的注册与命名
⑤ 解释执行source/Interpreter.ml递归遍历 AST,对 JSON 数据求值
⑥ JSON 编解码source/jotason/高性能读取与美化输出 JSON

整条链路非常清晰:文本 → token → AST → 执行结果,这也是所有脚本语言(如 jq、grep 方言)的标准做法。

🔤 词法分析:把文本切成"单词"

词法器source/Lexer.ml基于 OCaml 的sedlex库编写,它把查询字符串逐个字符扫描,产出带类型的 token。核心 token 类型定义在source/Lexer.mli中,大致分为几类:

  • 字面量INTSTRINGBOOLNULL
  • 标识符IDENTIFIER(键名)、FUNCTION(函数名)、VARIABLE$var
  • 运算符PIPE(管道|)、DOT.)、ALTERNATIVE??
  • 关键字IFTHENELSEFNTRYCATCH等控制流词

值得一提的是,token 类型里对数字做了精细区分:INTINT64BIG_INT(大整数)三种,这让 JSON 查询能无损处理超大整数,避免精度丢失。

词法器还有一个巧妙设计——字符串插值:模板字符串会被切成INTERP(插值片段)和TEMPLATEtoken,支持在查询中动态拼接表达式。

🌳 语法分析:构建抽象语法树

source/Parser.mli只暴露一个入口函数program,它消费 token 流,产出Ast.expression。AST 的定义全部在source/Ast.ml中,值得关注的几组结构:

  • 表达式Identity.)、Pipe(管道)、Operation(二元运算)、If_then_elseTry(异常处理)
  • 访问模式Key.foo)、Index.[1])、Slice.[0:3])、Dynamic_access.[$expr]动态取键)
  • 函数节点Fn0/Fn1/Fn2分别对应 0 参、1 参、2 参函数——这是整个语言函数体系的骨架
  • 构造函数List(数组字面量)、Object(对象字面量)

这种"函数按参数个数分型"的做法,让类型检查器可以提前约束每个函数能接几个参数,是比纯字符串匹配更稳健的设计。

📚 函数库:200+ 内置函数的注册中心

source/Language.ml是内置函数的"注册中心"。它为每个函数记录元信息:函数名、别名(兼容 jq 旧名)、描述、示例、适用类型(字符串/数组/对象…)和参数个数。这套元数据被多处复用:

  • CLI 的query-json --functions分类列出全部函数
  • REPL 的自动补全提示
  • 解析期的参数数量校验与报错

语言层面它做了一次"现代化改造":全部函数统一snake_case命名(如to_uppercase取代 jq 的ascii_upcase),null 访问默认报错而非静默传播,需要宽松行为时显式写.foo?。完整对照见 docs/JQ_COMPATIBILITY.md 文档。

⚙️ 解释执行:树遍历求值

source/Interpreter.ml是引擎心脏。它采用经典的树遍历解释器execute函数接收 AST 与 JSON 数据,递归地对每个表达式节点求值,最终返回Ok of Json.t list | Error of string | Halt of int三种结果——查询可能产出多个结果、失败、或以状态码中止。

解释器直接操作source/jotason/中的 JSON 值类型,省去了中间转换开销。jotason 模块内置了Json.ml(值模型)、Read.mll(手写词法器读取 JSON)、Write.ml(美化输出),是整个项目里性能优化最集中的地方。

🎯 错误系统:告诉你"为什么错、怎么改"

source/Error.ml让报错信息带上源代码位置。相比 jq 直接输出null,query-json 会指出哪个 token 出了问题、给出可用键名、甚至附上修复建议:

这类"可操作的错误信息"对新手极其友好,也说明错误处理被当作核心功能而非附属品来设计。

🖥️ 一份代码,三端运行

OCaml 的多后端能力是 query-json 最大的架构红利:

  • 原生二进制:编译为 macOS / Linux / Windows 可执行文件,基准测试显示比 jq 快 2~4 倍
  • 浏览器:通过 js 编译目标输出 JavaScript,驱动在线 playground(website/目录)
  • Node.js 库js/Js.ml提供 JS 绑定,可npm install使用

交互式 REPL 支持上下文感知补全:输入.提示键名,输入|提示函数:

更高级的过滤、分组、聚合用法可以参考cli/test/下的集成测试脚本,它们就是可执行的查询用例集:

📌 小结

query-json 展示了一个教科书级的查询语言实现路径:

  1. sedlex 词法分析→ token 流(数字类型精细分级)
  2. 递归下降解析→ 类型化的 AST(函数按元数分型)
  3. 元数据驱动的函数库→ 解析校验、补全、文档同源
  4. 树遍历解释器→ 直接操作 JSON 值,零中间层
  5. 位置感知的错误系统→ 新手友好的排错体验
  6. OCaml 多后端→ 一份源码覆盖 CLI / 浏览器 / Node.js

如果你想动手研究,可以从source/Core.mlparserun两个函数读起——50 行代码内就能看懂整条流水线的全貌。

【免费下载链接】query-jsonFaster, simpler and more portable implementation of jq-inspired language in OCaml项目地址: https://gitcode.com/gh_mirrors/qu/query-json

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 10:03:10

C#字节数组高效合并:Array.Copy、Buffer.BlockCopy与Span性能对比

1. 项目概述:从“拼接”到“高效复制”的思考 在C#开发中,处理字节数组( byte[] )是家常便饭,无论是网络通信、文件I/O、图像处理还是与硬件交互, byte[] 都是数据流转的基石。最近在做一个上位机项目…

作者头像 李华
网站建设 2026/8/25 10:01:53

大模型智能体面试:技术招聘的新范式与备战策略

1. 项目概述:大模型智能体面试时代的来临2026年的大模型智能体面试将彻底改变传统技术招聘的游戏规则。作为经历过三次技术浪潮的老程序员,我亲眼目睹了从白板手写代码到在线编程测试,再到如今基于大模型的智能体面试官的演进过程。这种新型面…

作者头像 李华
网站建设 2026/8/25 9:57:43

R语言实战:基于二项分布绘制OC曲线,量化评估抽样检验方案性能

1. 项目概述:从统计质量管理的核心工具到R语言实现在制造业、服务业乃至任何涉及流程与结果检验的领域,如何科学地评估一个抽样检验方案的好坏,是质量工程师和数据分析师必须面对的经典问题。一个常见的场景是:你设计了一个抽样方…

作者头像 李华
网站建设 2026/8/25 9:55:16

AI架构师核心能力与招聘实战指南

1. 为什么企业需要AI架构师?在数字化转型浪潮中,AI技术已从实验室走向产业应用的最前沿。我见过太多企业投入重金组建AI团队,却因为缺乏合格的AI架构师而导致项目烂尾。一个典型的失败案例是某金融公司花费800万构建的智能风控系统&#xff0…

作者头像 李华
网站建设 2026/8/25 9:55:13

VMware安装Rocky Linux 9:从零搭建Linux虚拟机实验环境

1. 项目概述:为什么选择VMware与Linux的组合?如果你刚接触软件开发、网络安全或者系统运维,听到“虚拟机”和“Linux”这两个词,可能会觉得有点门槛。但别担心,我今天要分享的,就是如何用最经典的工具VMwar…

作者头像 李华
网站建设 2026/8/25 9:49:08

在PongoOS中读取ARM64 CPU ID寄存器:检测指令集与硬件能力

1. 项目缘起:为什么要在PongoOS里读CPU寄存器?最近在折腾一台基于苹果M1芯片的设备,想搞清楚它到底支持哪些高级的ARMv8指令集扩展。这事儿听起来有点硬核,但动机其实很朴素:我想知道这台设备能不能跑某些依赖特定CPU特…

作者头像 李华