atdgen: strange generated JSON for sum type
Closed this issue · 5 comments
With this (simplified) example:
type t_kind = [ A of (int * int) | B of string ]<ocaml repr="classic">
type t_elem = { kind: t_kind; info: string; }
type t = t_elem list
and:
let example =
let a = Prog_t.{ kind = A (0, 0); info = "info" } in
let b = Prog_t.{ kind = B "hello"; info = "some info" } in
let c = Prog_t.{ kind = B "bye"; info = "some more info" } in
[ a ; b ; c]
let () =
let json = Prog_j.string_of_t example in
print_endline (Yojson.Safe.prettify json)
I get:
[
{ "kind": <"A": (0, 0)>, "info": "info" },
{ "kind": <"B": "hello">, "info": "some info" },
{ "kind": <"B": "bye">, "info": "some more info" }
]
What are these strange <...>
?
I was expecting:
[
{"kind":{"A":[0,0]},"info":"info"},
{"kind":{"B":"hello"},"info":"some info"},
{"kind":{"B":"bye"},"info":"some more info"}
]
Is it a bug? Something that I am doing wrong? How can I fix that?
@Karmaki I ran into this as well. Apparently you also need to pass -j-std
when invoking atdgen
to force it to encode variants into standard JSON types.
Great! Thank you for your suggestion @purefunctor. I'll try that ASAP.
OK, now I get:
[
{ "kind": [ "A", [ 0, 0 ] ], "info": "info" },
{ "kind": [ "B", "hello" ], "info": "some info" },
{ "kind": [ "B", "bye" ], "info": "some more info" }
]
which is a lot better, but not quite what I was expected... Why is the kind
an array and not an object? Is there a way to change that?
Why is the kind an array and not an object?
I reckon it's simply an opinionated encoding, maybe there's an optimization associated with it?
I think you can try this adapter if it's the encoding you want:
https://ocaml.org/p/atdgen-runtime/latest/doc/Atdgen_runtime/Json_adapter/One_field/index.html
Thanks. Just found it myself at the same time.
So with:
type t_pair = (int * int)
type t_kind = [
A of t_pair
| B of string
]<ocaml repr="classic"><json adapter.ocaml="Atdgen_runtime.Json_adapter.One_field">
type t_elem = { kind: t_kind; info: string; }
type t = t_elem list
I now get just what I wanted:
[
{ "kind": { "A": [ 0, 0 ] }, "info": "info" },
{ "kind": { "B": "hello" }, "info": "some info" },
{ "kind": { "B": "bye" }, "info": "some more info" }
]
Many thanks for your help. Closing this ticket then.