Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for custom conversion functions #10

Open
hcarty opened this issue Dec 17, 2021 · 1 comment
Open

Support for custom conversion functions #10

hcarty opened this issue Dec 17, 2021 · 1 comment
Labels
forwarded-to-js-devs This report has been forwarded to Jane Street's internal review system.

Comments

@hcarty
Copy link

hcarty commented Dec 17, 2021

Most libraries don't come with of_yojson and yojson_of functions. It would be very useful to be able to provide a custom module with (de)serialization functions or direct references to the functions.

An example of what direct references to custom functions might look like:

open Core_kernel

let time_of_yojson json =
  match json with
  | `String s -> Time_ns.of_string s
  | _ -> failwith "Invalid time"

let yojson_of_time time = `String (Time.to_string time)

type t = {
  label : string;
  timestamp: Time_ns.t; [@yojson_of time_of_yojson] [@of_yojson yojson_of_time]
}
[@@deriving yojson]

Those two functions can be wrapped in a module easily enough. However, that wrapping would make the type t definition more difficult to understand because we'd no longer see directly in the type that timestamp is a Time_ns.t.

An example with a custom module:

open Core_kernel

module Json = struct
  module Time_ns = struct
    type t = Time_ns.t

    let t_of_yojson json =
      match json with
      | `String s -> Time_ns.of_string s
      | _ -> failwith "Invalid time"
    ;;

    let yojson_of_t time = `String (Time.to_string time)
  end
end

type t = {
  label : string;
  timestamp : Time_ns.t; [@yojson.module Json.Time_ns]
}
[@@deriving yojson]

In this case we could directly replace timestamp : Time_ns.t with timestamp : Json.Time_ns.t but that requires a person reading the code to check and see what the definition of Json.Time_ns.t is. Specifying a custom module avoids placing that burden on reader.

@github-iron github-iron added the forwarded-to-js-devs This report has been forwarded to Jane Street's internal review system. label Dec 20, 2021
@hcarty
Copy link
Author

hcarty commented Dec 21, 2021

This would also help when using other ppx derivers alongside ppx_yojson_conv. For example, when using ppx_compare and [@@deriving equal, yojson] the following example would need an additional [@@deriving equal] on the type t = Time_ns.t alias as the deriver currently exists. With support for a syntax like the [@yojson.module Json.Time_ns] example above that extra annotation wouldn't be needed.

module Json = struct
  module Time_ns = struct
    type t = Time_ns.t

    let t_of_yojson json =
      match json with
      | `String s -> Time_ns.of_string s
      | _ -> failwith "Invalid time"
    ;;

    let yojson_of_t time = `String (Time.to_string time)
  end
end

type t = {
  label : string;
  timestamp : Json.Time_ns.t;
}
[@@deriving equal, yojson]
(* This will give an error because [Json.Time_ns.equal] does not exist *)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
forwarded-to-js-devs This report has been forwarded to Jane Street's internal review system.
Projects
None yet
Development

No branches or pull requests

2 participants