Library
Module
Module type
Parameter
Class
Class type
Derive decoders for a Decodeable.value
.
module M : Decodeable
type value = M.value
The type of values to be decoded (e.g. JSON or Yaml).
type error = value exposed_error
val pp_error : Format.formatter -> error -> unit
val string_of_error : error -> string
type 'a decoder = (M.value, 'a) exposed_decoder
The type of decoders.
Use the functions below to construct decoders for your data types.
To run a decoder, pass it to decode_value
.
val string : string decoder
Decode a string
.
val int : int decoder
Decode an int
.
val float : float decoder
Decode a float
.
val bool : bool decoder
Decode a bool
.
Decode a collection into an OCaml list, skipping elements for which the decoder returns None.
Decode a collection with an accumulator.
If we consider that an 'a decoder
is basically a type alias for json -> ('a, error) result
, the signature of this function is comparable to that of List.fold_left
:
val List.fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
val list_fold_left : ('a -> json -> ('a, error) result) -> 'a -> json -> ('a, error) result
val list_fold_left : ('a -> 'a decoder) -> 'a -> 'a decoder
fst |> uncons rest
decodes the first element of a list using fst
, then decodes the remainder of the list using rest
.
For example, to decode this s-expression:
(library
(name decoders))
we can use this decoder:
string |> uncons (function
| "library" -> field "name" string
| _ -> fail "Expected a library stanza")
As another example, say you have a JSON array that starts with a string, then a bool, then a list of integers:
["hello", true, 1, 2, 3, 4]
We could decode it like this:
let (>>=::) fst rest = uncons rest fst
let decoder : (string * bool * int list) decoder =
string >>=:: fun the_string ->
bool >>=:: fun the_bool ->
list int >>= fun the_ints ->
succeed (the_string, the_bool, the_ints)
(If you squint, the uncons operator >>=::
kind of looks like the cons operator ::
.)
Decode an object, where a particular field may or may not be present.
For example, (field_opt "hello" int)
:
{"hello": 123}
, will succeed with Some 123
{"hello": null}
, will fail{"world": 123}
, will succeed with None
["a", "list", "of", "strings"]
, will failDecode an object, requiring exactly one field.
maybe d
is a decoder that always succeeds. If d
succeeds with x
, then maybe d
succeeds with Some x
, otherwise if d
fails, then maybe d
succeeds with None
.
For example, maybe (field "hello" int)
:
{"hello": 123}
, will succeed with Some 123
{"hello": null}
, will succeed with None
{"world": 123}
, will succeed with None
["a", "list", "of", "strings"]
, will succeed with None
nullable d
will succeed with None
if the JSON value is null
. If the JSON value is non-null
, it wraps the result of running x
in a Some
.
For example, field "hello" (nullable int)
:
{"hello": 123}
, will succeed with Some 123
{"hello": null}
, will succeed with None
{"world": 123}
, will fail["a", "list", "of", "strings"]
, will failTry two decoders and then combine the result. We can use this to decode objects with many fields (but it's preferable to use Infix.(>>=)
- see the README).
val keys : string list decoder
Decode all of the keys of an object to a list of strings.
Decode an object into a list of key-value pairs.
Decode an object into a list of values, where the value decoder depends on the key.
keys'
is for when your keys might not be strings - probably only likely for Yaml.
val succeed : 'a -> 'a decoder
A decoder that always succeeds with the argument, ignoring the input.
val fail : string -> 'a decoder
A decoder that always fails with the given message, ignoring the input.
Create decoders that depend on previous results.
Recursive decoders.
let my_decoder = fix (fun my_decoder -> ...)
allows you to define my_decoder
in terms of itself.
module Infix : sig ... end
module Pipeline : sig ... end