Adding yojson deriver to third party code


Is there a way to extend an existing module so that it can be used with ppx_deriving_yojson?

Specifically I would like to be be able to have a record with Bignum.t fields that can be encoded / decoded to json via strings.

type t = {
  value : Bignum.t;
} [@@deriving yojson]

AFAICT it should be possible to somehow wrap the Bignum module with my own that adds the ppx rule but I can’t figure out a way of doing this.


I haven’t used it myself, but ppx_import claims to be able to do something like this in its README. ppx_import does apparently require a (slower?) staged preprocessing setup in dune though.

EDIT: I guess this works on single types rather than modules though. :frowning:

Since Bignum.t is an abstract type, you’ll need to define of_yojson and to_yojson functions yourself:

type bignum = Bignum.t

let bignum_to_yojson n = `String (Bignum.to_string_accurate n)

let bignum_of_yojson = function
  | `String n -> (
    try Ok (Bignum.of_string n)
    with e ->
      Error (Format.sprintf "Invalid Bignum: %s" (Printexc.to_string e)) )
  | json ->
      Error (Format.sprintf "Invalid Bignum: %s" (Yojson.Safe.to_string json))

type t = {value: bignum} [@@deriving yojson]

When you’re doing this for a non-abstract type, you can use ppx_import or simply duplicate the type:

module Person = struct
  type t =
    { first_name: string
    ; last_name: string }

module Company = struct
  type person = Person.t =
    { first_name: string
    ; last_name: string }
  [@@deriving yojson]

  type t =
    { employees: person list
    ; address: string }
  [@@deriving yojson]
1 Like

Perfect thanks. I was actually about to try that. :slight_smile: