Skip to content

Commit e5ef538

Browse files
committed
ppx: document ppx_deriving_json
1 parent aba5557 commit e5ef538

File tree

5 files changed

+142
-0
lines changed

5 files changed

+142
-0
lines changed

manual/menu.wiki

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
=Syntaxes
1313
==[[ppx|Ppx syntax extension]]
1414
==[[camlp4|Camlp4 syntax extension]]
15+
==[[ppx-deriving|Ppx deriving json]]
1516

1617
=Compiler
1718
==[[options|Command line options]]

manual/ppx-deriving.wiki

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
= Ppx deriver for serializing OCaml value to Json
2+
3+
The deriver is provided by the js_of_ocaml-ppx_deriving_json opam package.
4+
5+
The serialisation format follows js_of_ocaml's internal memory
6+
representation of OCaml values. It is not meant to be used to interact
7+
with 3rd party system. In practice, it can be used to exchange data
8+
between a js_of_ocaml program and a server side OCaml application.
9+
10+
The serialisation format allows a js_of_ocaml program to encode/decode
11+
OCaml value efficiently by leveraging JavaScript native Json
12+
support. See [Js_of_ocaml.Json.output] and [Js_of_ocaml.Json.output].
13+
14+
== Syntax
15+
16+
=== Generate serialisation from type definitions
17+
18+
One can derive serialisation functions from type definitions using
19+
the {{{[@@deriving ..]}}} attribute.
20+
21+
<<code language="ocaml"|
22+
23+
type t = A | B
24+
[@@deriving json]
25+
26+
val t_of_json : Deriving_Json_lexer.lexbuf -> t = <fun>
27+
val t_to_json : Buffer.t -> t -> unit = <fun>
28+
val t_json : t Deriving_Json.t = <abstr>
29+
30+
>>
31+
32+
=== Generate serialisation from types
33+
34+
One can generate an expression to serialise/deserialise value of an arbitrary type
35+
with the following syntax:
36+
37+
<<code language="ocaml"|
38+
39+
let (_ : t Deriving_json.t) = [%json: t]
40+
41+
let (_ : string -> t) = [%of_json: t]
42+
43+
let (_ : t -> string) = [%to_json: t]
44+
45+
>>

ppx/ppx_deriving_json/lib/ppx_deriving_json.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,19 @@ module Json_of = struct
789789
let deriver = Ppxlib.Deriving.add name ~extension
790790
end
791791
792+
module To_json = struct
793+
let name = "to_json"
794+
795+
let extension ~loc ~path:_ ctyp =
796+
[%expr
797+
fun x ->
798+
let buf = Buffer.create 50 in
799+
[%e write_of_type ctyp ~poly:false] buf x;
800+
Buffer.contents buf]
801+
802+
let deriver = Ppxlib.Deriving.add name ~extension
803+
end
804+
792805
module Json = struct
793806
let name = "json"
794807
@@ -803,6 +816,8 @@ end
803816
804817
let json_of = Json_of.deriver
805818
819+
let to_json = To_json.deriver
820+
806821
let of_json = Of_json.deriver
807822
808823
let json = Json.deriver

ppx/ppx_deriving_json/lib/ppx_deriving_json.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
val json_of : Ppxlib.Deriving.t
2121

22+
val to_json : Ppxlib.Deriving.t
23+
2224
val of_json : Ppxlib.Deriving.t
2325

2426
val json : Ppxlib.Deriving.t

ppx/ppx_deriving_json/tests/gen.mlt

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,3 +520,82 @@ val json :
520520
'a Deriving_Json.t -> 'b Deriving_Json.t -> ('a, 'b) t Deriving_Json.t =
521521
<fun>
522522
|}]
523+
524+
525+
type t = A | B [@@deriving json]
526+
[%%expect {|
527+
528+
type t =
529+
| A
530+
| B [@@deriving json] let _ = fun (_ : t) -> ()
531+
let rec (of_json : Deriving_Json_lexer.lexbuf -> t) =
532+
fun buf ->
533+
match Deriving_Json_lexer.read_case buf with
534+
| `Cst 1 -> B
535+
| `Cst 0 -> A
536+
| _ -> Deriving_Json_lexer.tag_error ~typename:"" buf let _ = of_json
537+
let rec (to_json : Buffer.t -> t -> unit) =
538+
fun buf ->
539+
function
540+
| B -> Deriving_Json.Json_int.write buf 1
541+
| A -> Deriving_Json.Json_int.write buf 0 let _ = to_json
542+
let (json : t Deriving_Json.t) = Deriving_Json.make to_json of_json
543+
let _ = json;;
544+
type t = A | B
545+
val of_json : Deriving_Json_lexer.lexbuf -> t = <fun>
546+
val to_json : Buffer.t -> t -> unit = <fun>
547+
val json : t Deriving_Json.t = <abstr>
548+
|}];;
549+
550+
let x = [%json: t option]
551+
[%%expect {|
552+
553+
let x =
554+
Deriving_Json.make
555+
(fun buf ->
556+
fun a ->
557+
Deriving_Json.write_option (fun buf -> fun a -> to_json buf a) buf a)
558+
(fun buf -> Deriving_Json.read_option (fun buf -> of_json buf) buf);;
559+
val x : t option Deriving_Json.t = <abstr>
560+
|}];;
561+
562+
let y = [%to_json: t list]
563+
[%%expect {|
564+
565+
let y x =
566+
let buf = Buffer.create 50 in
567+
((fun buf ->
568+
fun a ->
569+
Deriving_Json.write_list (fun buf -> fun a -> to_json buf a) buf a))
570+
buf x;
571+
Buffer.contents buf;;
572+
val y : t list -> string = <fun>
573+
|}];;
574+
575+
let z = [%json_of: t array]
576+
[%%expect {|
577+
578+
let z x =
579+
let buf = Buffer.create 50 in
580+
((fun buf ->
581+
fun a ->
582+
Deriving_Json.write_array (fun buf -> fun a -> to_json buf a) buf a))
583+
buf x;
584+
Buffer.contents buf;;
585+
val z : t array -> string = <fun>
586+
|}];;
587+
588+
let t = [%of_json: t * t]
589+
[%%expect {|
590+
591+
let t s =
592+
(fun buf ->
593+
Deriving_Json_lexer.read_lbracket buf;
594+
ignore (Deriving_Json_lexer.read_tag_1 0 buf);
595+
Deriving_Json_lexer.read_comma buf;
596+
(let a = of_json buf in
597+
Deriving_Json_lexer.read_comma buf;
598+
(let b = of_json buf in Deriving_Json_lexer.read_rbracket buf; (a, b))))
599+
(Deriving_Json_lexer.init_lexer (Lexing.from_string s));;
600+
val t : string -> t * t = <fun>
601+
|}]

0 commit comments

Comments
 (0)