Sam Schick
Sam Schick

Reputation: 430

How can I change how ppx_yojson_conv represents variants?

I'm trying to model write the elasticsearch DSL in ocaml types. frequently, there are things that are well modeled by variants where the tag is a singleton key in an object. For instance on interval queries, we might have a match, a prefix, a wildcard, etc. The DSL represents these like this;

{"match": {...match params}}
{"wildcard": {...wildcard params}}
{"prefix": {...prefix params}}

Writing out the yojson_of_x functions by hand seems like a huge amount of boilerplate, so I'd like to derive them, but ppx_yojson_conv says it represents variants like this;

["match", {...match_params}]

Is there a way to add some other annotation to get it to change its behavior? coming from rust world, serde calls this the "externally tagged" representation, but I don't know if it's possible to configure ppx_yojson_conv in a similar way.

Upvotes: 2

Views: 224

Answers (1)

octachron
octachron

Reputation: 18902

You cannot change the representation used by ppx_yojson_conv, but you can add a layer on top that does the conversion that you want:

let to_assoc: [> Yojson.Safe.t ] ->  Yojson.Safe.t as 'a  = function
  | `List (`String key::l) -> `Assoc [key,`List l]
  | x -> x

let to_list = function
  | `Assoc [key,`List l] -> `List (`String key::l)
  | x -> x

Then you can transform yojson converters to your own with:

type t =
  | A of int
  | B of int
[@@deriving yojson]
let yojson_of_t x = to_assoc (yojson_of_t x)
let t_of_yojson x = t_of_yojson (to_list x)

Upvotes: 3

Related Questions