Skip to content

Custom parsers

Anders Peter Fugmann edited this page Apr 30, 2019 · 2 revisions

It is possible to write custom parsers instead of using the ppx. Custom parsers must implement the function <type name>_of_<driver_name>_exn for deserialization, and <type_name>_to_<driver_name>. If parsing fails, the function must raise a <driver>.Protocol_error exception. Serializing function is not expected to fail.

Example using the json driver (ppx_protocol_conv_json)

open Protocol_conv_json
type time = Unix.tm
let time_of_json_exn t = 
  match Json.to_float t |> Unix.localtime with 
  | tm -> tm
  | exception Unix.(Unix_error (ERANGE, _, _)) -> 
    let err = Json.make_error ~value:t "Value not a valid timestamp" in
    raise (Json.Protocol_error err)

let time_to_json tm =
  Unix.mktime tm |> fst |> Json.of_float 

type t = { event: string; timestamp: time }
[@@deriving protocol ~driver:(module Json)]

(* Use the new t *)
let t = { event = "Ping"; timestamp=Unix.(localtime (gettimeofday ())) }
assert ((to_json t |> of_json_exn) = t);;

Collection data types / Parameterized types

To serialize and deserialize sets, maps et. al. its recommended to create a corresponding simple data structure:

let ('a, 'b) hashtbl = ('a, 'b) Hashtbl.t
let ('a, 'b) hashtbl_list = ('a, 'b) list [@@deriving protocol ~driver:(module Json)]
let hashtbl_of_json_exn deser_a deser_b json = hashtbl_list_of_json deser_a deser_b json |> List.to_seq |> Hashtbl.of_seq
let hashtbl_to_json ser_a ser_b t = Hashtbl.to_seq t |> List.of_seq |> hashtbl_list_to_json ser_a ser_b

The {de,}ser_{a,b} arguments are functions supplied by the ppx_protocol_conv framework for serializing and deserizalizing type parameters 'a and 'b.

Clone this wiki locally