Module Jsont.Query

JSON queries.

JSON queries are JSON types whose encoding direction may not specified. They can however be used to update JSON data without having to fully model it.

type error_kind =
  1. | Member_unbound of string * string list
  2. | Msg of string
  3. | Nth_unbound of int * int
  4. | Out_of_dom of string * string * string list
type error = error_kind * (Path.t * Meta.t)
type nonrec 'a t = 'a t

The type for JSON queries. A query either succeeds against a JSON value with a value of type 'a or it fails.

val query : 'a t -> Json.t -> ('a, error) Stdlib.result
val query_at_path : 'a t -> (Json.t * Path.t) -> ('a, error) Stdlib.result

sucess and failure

val succeed : 'a -> 'a t

succed v is a query that succeeds with value v on any JSON value.

val fail : error_kind -> 'a t

fail k is a query tha fails on any JSON with error kind k.

val app : ('a -> 'b) t -> 'a t -> 'b t
val product : 'a t -> 'b t -> ('a * 'b) t
val bind : 'a t -> ('a -> 'b t) -> 'b t
val map : ('a -> 'b) -> 'a t -> 'b t

JSON queries

val fold : null:'a t -> bool:'a t -> number:'a t -> string:'a t -> array:'a t -> obj:'a t -> 'a t
val partial_fold : ?null:'a t -> ?bool:'a t -> ?number:'a t -> ?string:'a t -> ?array:'a t -> ?obj:'a t -> 'a t
val json : Json.t t
val json_with_path : (Json.t * Path.t) t
val loc : (Path.t * Meta.t) t
val with_loc : 'a t -> ('a * Path.t * Meta.t) t

Null queries

val is_null : bool t
val null : unit t
val nullable : 'a t -> 'a option t

String queries

val string_to : kind:string -> (string -> ('a, string) Stdlib.result) -> 'a t
val enum : kind:string -> Stdlib.Set.Make(Stdlib.String).t -> string t
val enum_map : kind:string -> 'a Stdlib.Map.Make(Stdlib.String).t -> 'a t

Array queries

val is_empty_array : bool t
val hd : 'a t -> 'a t
val tl : 'a t -> 'a t
val fold_array : ('a -> 'b -> 'b) -> 'a t -> 'b t

Object queries

val mem_dom : validate:Stdlib.Set.Make(Stdlib.String).t option -> Stdlib.Set.Make(Stdlib.String).t t
val fold_obj : ('m -> 'a -> 'b -> 'b) -> (string -> ('m, string) Stdlib.result) -> 'a t -> 'b -> 'b t

Index and path queries

val get_nth : ?absent:'a -> int -> 'a t -> 'a t
val get_mem : ?absent:'a -> string -> 'a t -> 'a t
val get_index : ?absent:'a -> Path.index -> 'a t -> 'a t
val get_path : ?absent:'a -> Path.t -> 'a t -> 'a t


val delete_nth : must_exist:bool -> int -> Json.t t
val delete_mem : must_exist:bool -> string -> Json.t t
val delete_index : must_exist:bool -> Path.index -> Json.t t
val delete_path : must_exist:bool -> Path.t -> Json.t t


val set_nth : ?stub:Json.t -> must_exist:bool -> 'a t -> int -> 'a -> Json.t t
val set_mem : must_exist:bool -> 'a t -> string -> 'a -> Json.t t
val set_index : ?stub:Json.t -> must_exist:bool -> 'a t -> Path.index -> 'a -> Json.t t
val set_path : ?stub:Json.t -> must_exist:bool -> 'a t -> Path.t -> 'a -> Json.t t


val splice : ?stub:Json.t -> must_exist:bool -> 'a t -> Caret.t -> 'a -> Json.t t

Path & caret end-user syntax

Path and carets provide a way for end users to address JSON and edit locations.

A path is a sequence of key and list indexing operations. Applying the path to a JSON value leads to a JSON construct or nothing if one of the indices does not exist, or an error if ones tries to index a non-indexable value.

A caret is a path and a spatial specification for the JSON construct found by the path. The caret indicates either the void before that JSON construct, the JSON value itself (over) or the void after it.

Here are a few examples of paths and carets, syntactically the charater 'v' is used to denote the caret's insertion point before or after a path. There's no distinction between a path an over caret.

{ "ocaml":
      { "libs": ["jsont", "brr", "cmdliner"] }}
ocaml.libs        # value of member 'libs' of member 'ocaml'
ocaml.v[libs]     # void before the 'libs' member
ocaml.[libs]v     # void after 'libs' member

ocaml.libs.[0]    # first element of member 'libs' of member 'ocaml'
ocaml.libs.v[0]   # void before first element
ocaml.libs.[0]v   # void after first element

ocaml.libs.[-1]   # last element of member 'libs' of member 'ocaml'
ocaml.libs.v[-1]  # before last element (if any)
ocaml.libs.[-1]v  # after last element (if any)

More formally a path is a . seperated list of indices.

An index is written [i]. i can a zero-based list index with negative indices counting from the end of the list (-1 is the last element). Or i can be an object member name n. If there is no ambiguity, the surrounding brackets can be dropped.

A caret is a path whose last index brackets can be prefixed or suffixed by an insertion point, represented by the character 'v'. This respectively denote the void before or after the JSON construct found by the path.

Note. FIXME The syntax has no form of quoting at the moment this means key names can't contain, [, ], or start with a number.