Reputation: 9073
I'm using yojson
to parse a JSON file in OCaml, and while I'm validating the input file, I'd like to emit error messages containing source code information for the user.
For instance, if I found that a given value at line 5492 is not in the allowed range, I'd like to tell the user: "Invalid value in line source.json:5492".
How can I get this information?
(If yojson cannot give this kind of information, another OCaml JSON library that does have this information might be useful.)
Upvotes: 3
Views: 156
Reputation: 276
In between efficiency and interactivity, Yojson
has chosen the first (More accurately, Yojson
is really designed for data (de)serialisation, so computer generated JSON where error reporting makes no sense).
Its lever file: yojson/lib/read.mll
starts by the exact comment:
(*
We override Lexing.engine in order to avoid creating a new position
record each time a rule is matched.
This reduces total parsing time by about 31%.
*)
These positions are exactly what you need to report errors!
Jsonm
has what you need:
val decoded_range : decoder -> (int * int) * (int * int)
decoded_range d is the range of characters spanning the last `Lexeme or `Error (or `White or `Comment for an Jsonm.Uncut.decode) decoded by d. A pair of line and column numbers respectively one and zero based.
but Jsonm
is a library for experts.
Sadly, its wrapper Ezjsonm
does nearly the good thing but fails at the last second and raise Ezjsonm.Parse_error
with no range!
You can have a look at the source code as inspiration to do the right thing at https://github.com/mirage/ezjsonm/blob/master/lib/ezjsonm.ml : json_of_src
does exactly what you need but then ... for unknown reason ... from_src
defined as
let from_src src =
match json_of_src src with
| `JSON t -> t
| `Error (_,e) -> parse_error `Null "JSON.of_buffer %s" (string_of_error e)
let from_string str = from_src (`String str)
drops the range!
Upvotes: 5