1
votes

I'd like to generate JSON objects representing an AST, and I'm having a look at ppx_deriving_yojson to do that (more specifically the to_yojson part). Now, there are of course corner cases when I'd like to resort to a customized encoding. As mentioned in the documentation, customizing the representation of a record field is easy:

type bar = { test: int;
             test1: int [@to_yojson fun i -> `String (string_of_int i)] }
[@@deriving to_yojson]

let j1 = bar_to_yojson { test = 0; test1 = 1 }

will give me

val j1 : Yojson.Safe.t = `Assoc [("test", `Int 0); ("test1", `String "1")]

But there are places where I'd like to have a custom representation for the variant of a sum type, and the to_yojson attribute does not seem to be recognized here:

type foo = Bar | Bla of string [@to_yojson fun s -> `String (s ^ "_suffix")]
[@@deriving to_yojson]

let j2 = foo_to_yojson (Bla "bla")

gives me

val j2 : Yojson.Safe.t = `List [`String "Bla"; `String "bla"]

i.e. the default encoding of ppx_deriving_yojson. Is there something I am missing or is it simply not possible to achieve what I want?

NB: result are obtained with utop and #require "ppx_deriving_yojson";; as the first command

1

1 Answers

0
votes

I forgot about inline records. This would do roughly what I want:

type foo = Bar | Bla of { bla: string [@to_yojson fun s -> `String (s ^ "_suffix")]}
[@@deriving to_yojson]

let j2 = foo_to_yojson (Bla { bla = "bla"})

gives

val j2 : Yojson.Safe.t =
  `List [`String "Bla"; `Assoc [("bla", `String "bla_suffix")]]

However, while this solution works for a brand new development, it would imply a significant refactoring effort on existing types. Thus, I'm still looking for a less intrusive solution.