···10101111```ocaml
1212# open Jsont_pointer;;
1313+# #install_printer Jsont_pointer_top.printer;;
1314# let parse_json s =
1415 match Jsont_bytesrw.decode_string Jsont.json s with
1516 | Ok json -> json
···2021 | Ok s -> s
2122 | Error e -> failwith e;;
2223val json_to_string : Jsont.json -> string = <fun>
2323-# let show_pointer p =
2424- let idxs = indices p in
2525- let show_index = function
2626- | `Mem s -> "Mem:" ^ s
2727- | `Nth n -> "Nth:" ^ string_of_int n
2828- | `End -> "End"
2929- in
3030- "[" ^ String.concat ", " (List.map show_index idxs) ^ "]";;
3131-val show_pointer : t -> string = <fun>
3224```
33253426## What is JSON Pointer?
···71637264```ocaml
7365# let ptr = of_string "/users/0/name";;
7474-val ptr : t = <abstr>
6666+val ptr : t = [`Mem "users"; `Nth 0; `Mem "name"]
7567# get ptr users_json;;
7668- : Jsont.json = Jsont.String ("Alice", <abstr>)
7769```
···10193Let's see this in action:
1029410395```ocaml
104104-# let empty_ptr = of_string "";;
105105-val empty_ptr : t = <abstr>
106106-# show_pointer empty_ptr;;
107107-- : string = "[]"
9696+# of_string "";;
9797+- : t = []
10898```
10999110100The empty pointer has no reference tokens - it points to the root.
111101112102```ocaml
113113-# let foo_ptr = of_string "/foo";;
114114-val foo_ptr : t = <abstr>
115115-# show_pointer foo_ptr;;
116116-- : string = "[Mem:foo]"
103103+# of_string "/foo";;
104104+- : t = [`Mem "foo"]
117105```
118106119107The pointer `/foo` has one token: `foo`. Since it's not a number, it's
120108interpreted as an object member name (`Mem`).
121109122110```ocaml
123123-# let foo_0_ptr = of_string "/foo/0";;
124124-val foo_0_ptr : t = <abstr>
125125-# show_pointer foo_0_ptr;;
126126-- : string = "[Mem:foo, Nth:0]"
111111+# of_string "/foo/0";;
112112+- : t = [`Mem "foo"; `Nth 0]
127113```
128114129115Here we have two tokens: `foo` (a member name) and `0` (interpreted as
130116an array index `Nth`).
131117132118```ocaml
133133-# show_pointer (of_string "/foo/bar/baz");;
134134-- : string = "[Mem:foo, Mem:bar, Mem:baz]"
119119+# of_string "/foo/bar/baz";;
120120+- : t = [`Mem "foo"; `Mem "bar"; `Mem "baz"]
135121```
136122137123Multiple tokens navigate deeper into nested structures.
···171157- : (t, string) result =
172158Error "Invalid JSON Pointer: must be empty or start with '/': foo"
173159# of_string_result "/valid";;
174174-- : (t, string) result = Ok <abstr>
160160+- : (t, string) result = Ok [`Mem "valid"]
175161```
176162177163## Evaluation: Navigating JSON
···285271286272```ocaml
287273# let slash_ptr = make [`Mem "a/b"];;
288288-val slash_ptr : t = <abstr>
274274+val slash_ptr : t = [`Mem "a/b"]
289275# to_string slash_ptr;;
290276- : string = "/a~1b"
291277# get slash_ptr rfc_example |> json_to_string;;
···358344> note that leading zeros are not allowed
359345360346```ocaml
361361-# show_pointer (of_string "/foo/0");;
362362-- : string = "[Mem:foo, Nth:0]"
347347+# of_string "/foo/0";;
348348+- : t = [`Mem "foo"; `Nth 0]
363349```
364350365351Zero itself is fine.
366352367353```ocaml
368368-# show_pointer (of_string "/foo/01");;
369369-- : string = "[Mem:foo, Mem:01]"
354354+# of_string "/foo/01";;
355355+- : t = [`Mem "foo"; `Mem "01"]
370356```
371357372358But `01` has a leading zero, so it's NOT treated as an array index - it
···384370how it parses:
385371386372```ocaml
387387-# show_pointer (of_string "/foo/-");;
388388-- : string = "[Mem:foo, End]"
373373+# of_string "/foo/-";;
374374+- : t = [`Mem "foo"; `End]
389375```
390376391377The `-` is recognized as a special `End` index.
···562548563549```ocaml
564550# let p = make [`Mem "a/b"];;
565565-val p : t = <abstr>
551551+val p : t = [`Mem "a/b"]
566552# to_string p;;
567553- : string = "/a~1b"
568568-# let p' = of_string "/a~1b";;
569569-val p' : t = <abstr>
570570-# show_pointer p';;
571571-- : string = "[Mem:a/b]"
554554+# of_string "/a~1b";;
555555+- : t = [`Mem "a/b"]
572556```
573557574558### Escaping in Action
···663647664648```ocaml
665649# let port_ptr = make [`Mem "database"; `Mem "port"];;
666666-val port_ptr : t = <abstr>
650650+val port_ptr : t = [`Mem "database"; `Mem "port"]
667651# to_string port_ptr;;
668652- : string = "/database/port"
669653```
···672656673657```ocaml
674658# let first_feature_ptr = make [`Mem "features"; `Nth 0];;
675675-val first_feature_ptr : t = <abstr>
659659+val first_feature_ptr : t = [`Mem "features"; `Nth 0]
676660# to_string first_feature_ptr;;
677661- : string = "/features/0"
678662```
···683667684668```ocaml
685669# let db_ptr = of_string "/database";;
686686-val db_ptr : t = <abstr>
670670+val db_ptr : t = [`Mem "database"]
687671# let creds_ptr = append db_ptr (`Mem "credentials");;
688688-val creds_ptr : t = <abstr>
672672+val creds_ptr : t = [`Mem "database"; `Mem "credentials"]
689673# let user_ptr = append creds_ptr (`Mem "username");;
690690-val user_ptr : t = <abstr>
674674+val user_ptr : t = [`Mem "database"; `Mem "credentials"; `Mem "username"]
691675# to_string user_ptr;;
692676- : string = "/database/credentials/username"
693677```
···696680697681```ocaml
698682# let base = of_string "/api/v1";;
699699-val base : t = <abstr>
683683+val base : t = [`Mem "api"; `Mem "v1"]
700684# let endpoint = of_string "/users/0";;
701701-val endpoint : t = <abstr>
685685+val endpoint : t = [`Mem "users"; `Nth 0]
702686# to_string (concat base endpoint);;
703687- : string = "/api/v1/users/0"
704688```
+10
src/jsont_pointer.ml
···253253let pp ppf p =
254254 Format.pp_print_string ppf (to_string p)
255255256256+let pp_verbose ppf p =
257257+ let pp_index ppf = function
258258+ | `Mem s -> Format.fprintf ppf "`Mem %S" s
259259+ | `Nth n -> Format.fprintf ppf "`Nth %d" n
260260+ | `End -> Format.fprintf ppf "`End"
261261+ in
262262+ Format.fprintf ppf "[%a]"
263263+ (Format.pp_print_list ~pp_sep:(fun ppf () -> Format.fprintf ppf "; ") pp_index)
264264+ (indices p)
265265+256266(* Comparison *)
257267258268let segment_equal s1 s2 = match s1, s2 with
+5
src/jsont_pointer.mli
···189189val pp : Format.formatter -> t -> unit
190190(** [pp] formats a pointer using {!to_string}. *)
191191192192+val pp_verbose : Format.formatter -> t -> unit
193193+(** [pp_verbose] formats a pointer showing its index structure.
194194+ For example, [/foo/0/-] is formatted as [[`Mem "foo"; `Nth 0; `End]].
195195+ Useful for debugging and understanding pointer structure. *)
196196+192197(** {2:comparison Comparison} *)
193198194199val equal : t -> t -> bool