You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OCaml中如何获取JSON Token位置信息以生成精准错误提示?

获取JSON解析时的源码位置(OCaml)

首先说下你用的yojson库:默认情况下,yojson解析后的AST是不携带源码位置信息的,不过如果只是处理解析阶段的语法错误,你可以手动调用它的底层Lexer和Parser模块来捕获位置:

  • 你需要手动构建解析流程,给lexbuf设置文件名,这样出错时就能拿到包含文件名、行号、列号的位置信息。比如这段示例代码:
open Yojson.Safe

let parse_with_error_pos filename =
  let ic = open_in filename in
  let lexbuf = Lexing.from_channel ic in
  Lexing.set_filename lexbuf filename;  (* 让位置信息带上文件名 *)
  try
    let json = Parser.json Lexer.token lexbuf in
    close_in ic;
    Ok json
  with
  | Lexer.Error msg ->
      let pos = lexbuf.Lexing.lex_curr_p in
      close_in ic;
      Error (Printf.sprintf "Lex error at %s:%d:%d: %s" pos.pos_fname pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1) msg)
  | Parser.Error ->
      let pos = lexbuf.Lexing.lex_curr_p in
      close_in ic;
      Error (Printf.sprintf "Parse error at %s:%d:%d" pos.pos_fname pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1))

但如果是自定义验证逻辑(比如检查某个值是否在允许范围内),yojson的AST本身不记录每个节点的位置,这时候用yojson就会很麻烦——你没法知道哪个节点对应源码里的哪一行。

这时候推荐几个支持位置追踪的OCaml JSON库:

1. yojson-located

这是yojson的官方扩展,它会在解析后的AST节点中嵌入位置信息。安装后,你可以用Yojson_located.Safe.from_file来解析文件,得到的每个JSON节点都带有loc字段,包含文件名、起始/结束行号、列号等信息。验证的时候,直接读取这个字段就能输出精确的错误提示,完美适配你原来的yojson使用习惯。

2. Jsonm

这是一个流式、事件驱动的JSON解析库,它在解析每个JSON元素(比如对象、数组、字符串、数字)时,都能实时获取当前的源码位置。你可以在遍历元素的同时做验证,一旦发现非法值,立刻输出对应的位置信息。示例代码大概是这样:

open Jsonm

let validate_with_pos filename =
  let ic = open_in filename in
  let src = `Channel ic in
  let dec = decoder src in
  let rec process_elements () =
    match decode dec with
    | `Lexeme lexeme ->
        let pos = decoder_pos dec in
        (* 这里写你的验证逻辑,比如检查整数范围 *)
        (match lexeme with
         | `Int n when n < 0 || n > 100 ->
             Printf.printf "Invalid value in %s:%d:%d: integer %d is out of allowed range\n" filename pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1) n
         | _ -> ());
        process_elements ()
    | `End -> close_in ic; Ok ()
    | `Error err ->
        let pos = decoder_pos dec in
        close_in ic;
        Error (Printf.sprintf "Parsing error at %s:%d:%d: %s" filename pos.pos_lnum (pos.pos_cnum - pos.pos_bol + 1) (error_message err))
  in
  process_elements ()

3. Json-wheel

这个库也支持在AST中保存位置信息,它的Json.t类型每个节点都包含位置数据,解析时默认就会追踪这些信息,验证时直接提取即可。

如果只是想在yojson的基础上扩展,优先选yojson-located,不需要改太多代码;如果需要更灵活的流式处理,Jsonm是不错的选择。

内容的提问来源于stack exchange,提问作者anol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:23:12