Declarative JSON data manipulation for OCaml
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Tighten ocaml-json API knobs

+68 -69
+16 -9
lib/codec.ml
··· 13 13 exception Error = Loc.Error 14 14 15 15 type 'a node = 'a * Meta.t 16 + type meta = [ `None | `Locs | `Full ] 16 17 17 18 type ('ret, 'f) dec_fun = 18 19 | Dec_fun : 'f -> ('ret, 'f) dec_fun ··· 2232 2233 ws : tokbuf; (* Bufferizes whitespace when layout is [true]. *) 2233 2234 } 2234 2235 2235 - let decoder ?(locs = false) ?(layout = false) ?(file = "-") reader = 2236 + let meta_flags = function 2237 + | `None -> (false, false) 2238 + | `Locs -> (true, false) 2239 + | `Full -> (true, true) 2240 + 2241 + let decoder ?(meta = `None) ?(file = "-") reader = 2242 + let locs, layout = meta_flags meta in 2236 2243 let overlap = Stdlib.Bytes.create uchar_max_utf8_bytes in 2237 2244 let token = tokbuf_create 255 and ws = tokbuf_create 255 in 2238 2245 let meta_none = Meta.make (Loc.(set_file none) file) in ··· 3213 3220 | u when is_number_start u -> case d t map.dec_number 3214 3221 | _ -> err_not_json_value d 3215 3222 3216 - let of_reader_exn ?layout ?locs ?file t reader = 3217 - let d = decoder ?layout ?locs ?file reader in 3223 + let of_reader_exn ?meta ?file t reader = 3224 + let d = decoder ?meta ?file reader in 3218 3225 let v = 3219 3226 nextc d; 3220 3227 parse d t 3221 3228 in 3222 3229 if d.u <> eot then err_exp_eot d else v 3223 3230 3224 - let of_reader ?layout ?locs ?file t reader = 3225 - try Ok (of_reader_exn ?layout ?locs ?file t reader) with Error e -> Error e 3231 + let of_reader ?meta ?file t reader = 3232 + try Ok (of_reader_exn ?meta ?file t reader) with Error e -> Error e 3226 3233 3227 - let of_string_exn ?layout ?locs ?file t s = 3228 - of_reader_exn ?layout ?locs ?file t (Bytes.Reader.of_string s) 3234 + let of_string_exn ?meta ?file t s = 3235 + of_reader_exn ?meta ?file t (Bytes.Reader.of_string s) 3229 3236 3230 - let of_string ?layout ?locs ?file t s = 3231 - of_reader ?layout ?locs ?file t (Bytes.Reader.of_string s) 3237 + let of_string ?meta ?file t s = 3238 + of_reader ?meta ?file t (Bytes.Reader.of_string s) 3232 3239 3233 3240 (* Encoding *) 3234 3241
+12 -16
lib/codec.mli
··· 81 81 type 'a node = 'a * Meta.t 82 82 (** A payload with node metadata. *) 83 83 84 + type meta = [ `None | `Locs | `Full ] 85 + (** Metadata captured while decoding: 86 + - [`None] captures no locations or layout. This is the default and fastest 87 + mode. 88 + - [`Locs] captures source locations for parsed nodes and errors. 89 + - [`Full] captures source locations and surrounding whitespace, enabling 90 + layout-preserving output with [~preserve:true]. *) 91 + 84 92 module Path = Loc.Path 85 93 (** JSON paths used by query and update codecs. *) 86 94 ··· 904 912 905 913 module Stream : sig 906 914 val of_reader : 907 - ?layout:bool -> 908 - ?locs:bool -> 915 + ?meta:meta -> 909 916 ?file:string -> 910 917 'a t -> 911 918 Bytesrw.Bytes.Reader.t -> 912 919 ('a, Error.t) result 913 920 914 921 val of_reader_exn : 915 - ?layout:bool -> 916 - ?locs:bool -> 917 - ?file:string -> 918 - 'a t -> 919 - Bytesrw.Bytes.Reader.t -> 920 - 'a 922 + ?meta:meta -> ?file:string -> 'a t -> Bytesrw.Bytes.Reader.t -> 'a 921 923 922 924 val of_string : 923 - ?layout:bool -> 924 - ?locs:bool -> 925 - ?file:string -> 926 - 'a t -> 927 - string -> 928 - ('a, Error.t) result 925 + ?meta:meta -> ?file:string -> 'a t -> string -> ('a, Error.t) result 929 926 930 - val of_string_exn : 931 - ?layout:bool -> ?locs:bool -> ?file:string -> 'a t -> string -> 'a 927 + val of_string_exn : ?meta:meta -> ?file:string -> 'a t -> string -> 'a 932 928 933 929 val to_writer : 934 930 ?buf:Bytes.t ->
+10 -9
lib/json.ml
··· 33 33 | Object of object' node 34 34 35 35 type number_format = Value.number_format 36 + type meta = Codec.meta 36 37 37 38 let pp = Value.pp 38 39 let decode = Codec.decode 39 40 let decode_exn = Codec.decode_exn 40 41 let encode = Codec.encode 41 42 42 - let pp_value ?(number_format = Value.default_number_format) t () ppf v = 43 + let pp_value ?(number_format = Value.default_number_format) t ppf v = 43 44 match encode t v with 44 45 | j -> Value.pp' number_format ppf j 45 46 | exception Error e -> Value.pp_string ppf (Loc.Error.to_string e) ··· 56 57 module Value = struct 57 58 include Value 58 59 59 - let of_string ?layout ?locs ?file s = 60 - Codec.Stream.of_string ?layout ?locs ?file Codec.Value.t s 60 + let of_string ?meta ?file s = 61 + Codec.Stream.of_string ?meta ?file Codec.Value.t s 61 62 62 - let of_string_exn ?layout ?locs ?file s = 63 - Codec.Stream.of_string_exn ?layout ?locs ?file Codec.Value.t s 63 + let of_string_exn ?meta ?file s = 64 + Codec.Stream.of_string_exn ?meta ?file Codec.Value.t s 64 65 65 - let of_reader ?layout ?locs ?file r = 66 - Codec.Stream.of_reader ?layout ?locs ?file Codec.Value.t r 66 + let of_reader ?meta ?file r = 67 + Codec.Stream.of_reader ?meta ?file Codec.Value.t r 67 68 68 - let of_reader_exn ?layout ?locs ?file r = 69 - Codec.Stream.of_reader_exn ?layout ?locs ?file Codec.Value.t r 69 + let of_reader_exn ?meta ?file r = 70 + Codec.Stream.of_reader_exn ?meta ?file Codec.Value.t r 70 71 71 72 let to_string ?buf ?indent ?preserve ?number_format v = 72 73 Codec.Stream.to_string ?buf ?indent ?preserve ?number_format Codec.Value.t v
+21 -28
lib/json.mli
··· 88 88 type number_format = Value.number_format 89 89 (** The type for JSON number formatters. *) 90 90 91 + type meta = Codec.meta 92 + (** Metadata captured while decoding: 93 + - [`None] captures no locations or layout. This is the default and fastest 94 + mode. 95 + - [`Locs] captures source locations for parsed nodes and errors. 96 + - [`Full] captures source locations and surrounding whitespace, enabling 97 + layout-preserving output with [~preserve:true]. *) 98 + 91 99 module Error = Error 92 100 (** Typed JSON errors. See {!module-Error} for the full set. *) 93 101 ··· 123 131 Use {!Value.of_string} if you specifically want a generic {!type-t} tree. *) 124 132 125 133 val of_reader : 126 - ?layout:bool -> 127 - ?locs:bool -> 134 + ?meta:meta -> 128 135 ?file:fpath -> 129 136 'a codec -> 130 137 Bytes.Reader.t -> 131 138 ('a, Error.t) result 132 139 (** [of_reader t r] decodes a value from [r] according to [t]. 133 - - If [layout] is [true] whitespace is preserved in {!Meta.t} values. 134 - Defaults to [false]. 135 - - If [locs] is [true] locations are preserved in {!Meta.t} values and error 136 - messages are precisely located. Defaults to [false]. 140 + - [meta] controls whether source locations and layout are preserved. 141 + Defaults to [`None]. 137 142 - [file] is the file path from which [r] is assumed to read. Defaults to the 138 143 empty path. *) 139 144 140 145 val of_reader_exn : 141 - ?layout:bool -> ?locs:bool -> ?file:fpath -> 'a codec -> Bytes.Reader.t -> 'a 146 + ?meta:meta -> ?file:fpath -> 'a codec -> Bytes.Reader.t -> 'a 142 147 (** [of_reader_exn] is like {!val-of_reader} but raises {!Json.exception-Error}. 143 148 *) 144 149 145 150 val of_string : 146 - ?layout:bool -> 147 - ?locs:bool -> 148 - ?file:fpath -> 149 - 'a codec -> 150 - string -> 151 - ('a, Error.t) result 151 + ?meta:meta -> ?file:fpath -> 'a codec -> string -> ('a, Error.t) result 152 152 (** [of_string c s] decodes [s] directly with codec [c]. *) 153 153 154 - val of_string_exn : 155 - ?layout:bool -> ?locs:bool -> ?file:fpath -> 'a codec -> string -> 'a 154 + val of_string_exn : ?meta:meta -> ?file:fpath -> 'a codec -> string -> 'a 156 155 (** [of_string_exn] is like {!val-of_string} but raises {!Json.exception-Error}. 157 156 *) 158 157 ··· 211 210 {!Json.val-to_string}, etc., using the identity codec ({!Codec.Value.t}). 212 211 *) 213 212 214 - val of_string : 215 - ?layout:bool -> ?locs:bool -> ?file:fpath -> string -> (t, Error.t) result 213 + val of_string : ?meta:meta -> ?file:fpath -> string -> (t, Error.t) result 216 214 (** [of_string s] parses [s] to a generic JSON value. *) 217 215 218 - val of_string_exn : ?layout:bool -> ?locs:bool -> ?file:fpath -> string -> t 216 + val of_string_exn : ?meta:meta -> ?file:fpath -> string -> t 219 217 (** [of_string_exn] is like {!val-of_string} but raises 220 218 {!Json.exception-Error}. *) 221 219 222 220 val of_reader : 223 - ?layout:bool -> 224 - ?locs:bool -> 225 - ?file:fpath -> 226 - Bytesrw.Bytes.Reader.t -> 227 - (t, Error.t) result 221 + ?meta:meta -> ?file:fpath -> Bytesrw.Bytes.Reader.t -> (t, Error.t) result 228 222 (** [of_reader r] parses [r] to a generic JSON value. *) 229 223 230 - val of_reader_exn : 231 - ?layout:bool -> ?locs:bool -> ?file:fpath -> Bytesrw.Bytes.Reader.t -> t 224 + val of_reader_exn : ?meta:meta -> ?file:fpath -> Bytesrw.Bytes.Reader.t -> t 232 225 (** [of_reader_exn] is like {!val-of_reader} but raises 233 226 {!Json.exception-Error}. *) 234 227 ··· 258 251 val pp : t Fmt.t 259 252 (** [pp] formats JSON values. Alias of {!Value.pp}. *) 260 253 261 - val pp_value : ?number_format:number_format -> 'a codec -> unit -> 'a Fmt.t 262 - (** [pp_value c ()] formats values of type ['a] by encoding them with codec [c] 263 - and pretty-printing the resulting JSON. A codec error is formatted as a JSON 254 + val pp_value : ?number_format:number_format -> 'a codec -> 'a Fmt.t 255 + (** [pp_value c] formats values of type ['a] by encoding them with codec [c] and 256 + pretty-printing the resulting JSON. A codec error is formatted as a JSON 264 257 string carrying the error message, so this function always produces valid 265 258 JSON. *) 266 259
+4 -3
test/codecs/geojson.ml
··· 335 335 | file -> In_channel.with_open_bin file (process file) 336 336 with Sys_error e -> Error e 337 337 338 - let trip ~file ~indent ~locs ~dec_only = 338 + let trip ~file ~indent ~meta ~dec_only = 339 339 log_if_error ~use:1 @@ with_infile file 340 340 @@ fun r -> 341 341 log_if_error ~use:1 342 342 @@ 343 - let* t = Json.of_reader ~file ~locs Geojson.codec r in 343 + let* t = Json.of_reader ~file ~meta Geojson.codec r in 344 344 if dec_only then Ok 0 345 345 else 346 346 let w = Bytesrw.Bytes.Writer.of_out_channel stdout in ··· 367 367 let doc = "Decode only." in 368 368 Arg.(value & flag & info [ "d" ] ~doc) 369 369 in 370 - trip ~file ~indent ~locs ~dec_only 370 + let meta = if locs then `Locs else `None in 371 + trip ~file ~indent ~meta ~dec_only 371 372 372 373 let main () = Cmd.eval' geojson 373 374 let () = if !Sys.interactive then () else exit (main ())
+1 -1
test/codecs/quickstart.ml
··· 16 16 let correct = 17 17 Result.map 18 18 (fun v -> Json.to_string ~preserve:true update v) 19 - (Json.of_string ~layout:true update data) 19 + (Json.of_string ~meta:`Full update data) 20 20 in 21 21 print_endline (Result.get_ok correct) 22 22
+4 -3
test/codecs/topojson.ml
··· 296 296 | file -> In_channel.with_open_bin file (process file) 297 297 with Sys_error e -> Error e 298 298 299 - let trip ~file ~indent ~locs ~dec_only = 299 + let trip ~file ~indent ~meta ~dec_only = 300 300 log_if_error ~use:1 @@ with_infile file 301 301 @@ fun r -> 302 302 log_if_error ~use:1 303 303 @@ 304 - let* t = Json.of_reader ~file ~locs Topology.codec r in 304 + let* t = Json.of_reader ~file ~meta Topology.codec r in 305 305 if dec_only then Ok 0 306 306 else 307 307 let w = Bytesrw.Bytes.Writer.of_out_channel stdout in ··· 328 328 let doc = "Decode only." in 329 329 Arg.(value & flag & info [ "d" ] ~doc) 330 330 in 331 - trip ~file ~indent ~locs ~dec_only 331 + let meta = if locs then `Locs else `None in 332 + trip ~file ~indent ~meta ~dec_only 332 333 333 334 let main () = Cmd.eval' topojson 334 335 let () = if !Sys.interactive then () else exit (main ())