3
type json = [%import: Yojson.Safe.json] [@@deriving show]
8
[%import: 'a Ppx_deriving_yojson_runtime.error_or] [@@deriving show]
12
let assert_roundtrip pp_obj to_json of_json obj str =
13
let json = Yojson.Safe.from_string str in
14
let cleanup json = Yojson.Safe.(json |> to_string |> from_string) in
15
assert_equal ~printer:show_json json (cleanup (to_json obj));
16
assert_equal ~printer:(show_error_or pp_obj) (Result.Ok obj) (of_json json)
18
let assert_failure pp_obj of_json err str =
19
let json = Yojson.Safe.from_string str in
20
assert_equal ~printer:(show_error_or pp_obj) (Result.Error err) (of_json json)
22
type u = unit [@@deriving show, yojson]
23
type i1 = int [@@deriving show, yojson]
24
type i2 = int32 [@@deriving show, yojson]
25
type i3 = Int32.t [@@deriving show, yojson]
26
type i4 = int64 [@@deriving show, yojson]
27
type i5 = Int64.t [@@deriving show, yojson]
28
type i6 = nativeint [@@deriving show, yojson]
29
type i7 = Nativeint.t [@@deriving show, yojson]
30
type i8 = int64 [@encoding `string] [@@deriving show, yojson]
31
type i9 = nativeint [@encoding `string] [@@deriving show, yojson]
32
type f = float [@@deriving show, yojson]
33
type b = bool [@@deriving show, yojson]
34
type c = char [@@deriving show, yojson]
35
type s = string [@@deriving show, yojson]
36
type y = bytes [@@deriving show, yojson]
37
type xr = int ref [@@deriving show, yojson]
38
type xo = int option [@@deriving show, yojson]
39
type xl = int list [@@deriving show, yojson]
40
type xa = int array [@@deriving show, yojson]
41
type xt = int * int [@@deriving show, yojson]
44
[@@deriving show, yojson]
45
type pv = [ `A | `B of int | `C of int * string ]
46
[@@deriving show, yojson]
47
type pva = [ `A ] and pvb = [ `B ]
48
[@@deriving show, yojson]
49
type 'a pvc = [ `C of 'a ]
50
[@@deriving show, yojson]
51
type pvd = [ pva | pvb | int pvc ]
52
[@@deriving show, yojson]
54
type v = A | B of int | C of int * string
55
[@@deriving show, yojson]
56
type r = { x : int; y : string }
57
[@@deriving show, yojson]
58
#if OCAML_VERSION >= (4, 03, 0)
59
type rv = RA | RB of int | RC of int * string | RD of { z : string }
60
[@@deriving show, yojson]
64
assert_roundtrip pp_u u_to_yojson u_of_yojson
68
assert_roundtrip pp_i1 i1_to_yojson i1_of_yojson
70
assert_roundtrip pp_i2 i2_to_yojson i2_of_yojson
72
assert_roundtrip pp_i3 i3_to_yojson i3_of_yojson
74
assert_roundtrip pp_i4 i4_to_yojson i4_of_yojson
76
assert_roundtrip pp_i5 i5_to_yojson i5_of_yojson
78
assert_roundtrip pp_i6 i6_to_yojson i6_of_yojson
80
assert_roundtrip pp_i7 i7_to_yojson i7_of_yojson
82
assert_roundtrip pp_i8 i8_to_yojson i8_of_yojson
84
assert_roundtrip pp_i9 i9_to_yojson i9_of_yojson
87
let test_int_edge ctxt =
88
assert_roundtrip pp_i2 i2_to_yojson i2_of_yojson
89
0x7fffffffl "2147483647";
90
assert_roundtrip pp_i2 i2_to_yojson i2_of_yojson
91
(Int32.neg 0x80000000l) "-2147483648";
92
assert_roundtrip pp_i4 i4_to_yojson i4_of_yojson
93
0x7fffffffffffffffL "9223372036854775807";
94
assert_roundtrip pp_i4 i4_to_yojson i4_of_yojson
95
(Int64.neg 0x8000000000000000L) "-9223372036854775808"
98
assert_roundtrip pp_f f_to_yojson f_of_yojson
100
assert_equal ~printer:(show_error_or pp_f)
102
(f_of_yojson (`Int 1))
105
assert_roundtrip pp_b b_to_yojson b_of_yojson
107
assert_roundtrip pp_b b_to_yojson b_of_yojson
111
assert_roundtrip pp_c c_to_yojson c_of_yojson
113
assert_failure pp_c c_of_yojson
114
"Test_ppx_yojson.c" "\"xxx\""
116
let test_string ctxt =
117
assert_roundtrip pp_s s_to_yojson s_of_yojson
119
assert_roundtrip pp_y y_to_yojson y_of_yojson
120
(Bytes.of_string "foo") "\"foo\""
123
assert_roundtrip pp_xr xr_to_yojson xr_of_yojson
126
let test_option ctxt =
127
assert_roundtrip pp_xo xo_to_yojson xo_of_yojson
129
assert_roundtrip pp_xo xo_to_yojson xo_of_yojson
133
assert_roundtrip pp_xl xl_to_yojson xl_of_yojson
135
assert_roundtrip pp_xl xl_to_yojson xl_of_yojson
138
let test_array ctxt =
139
assert_roundtrip pp_xa xa_to_yojson xa_of_yojson
141
assert_roundtrip pp_xa xa_to_yojson xa_of_yojson
142
[|42; 43|] "[42, 43]"
144
let test_tuple ctxt =
145
assert_roundtrip pp_xt xt_to_yojson xt_of_yojson
149
assert_roundtrip (pp_p pp_i1) (p_to_yojson i1_to_yojson) (p_of_yojson i1_of_yojson)
151
assert_roundtrip (pp_p pp_i1) (p_to_yojson i1_to_yojson) (p_of_yojson i1_of_yojson)
155
assert_roundtrip pp_pv pv_to_yojson pv_of_yojson
157
assert_roundtrip pp_pv pv_to_yojson pv_of_yojson
158
(`B 42) "[\"B\", 42]";
159
assert_roundtrip pp_pv pv_to_yojson pv_of_yojson
160
(`C (42, "foo")) "[\"C\", 42, \"foo\"]";
161
assert_roundtrip pp_pvd pvd_to_yojson pvd_of_yojson
163
assert_roundtrip pp_pvd pvd_to_yojson pvd_of_yojson
165
assert_roundtrip pp_pvd pvd_to_yojson pvd_of_yojson
167
assert_equal ~printer:(show_error_or pp_pvd)
168
(Result.Error "Test_ppx_yojson.pvd")
169
(pvd_of_yojson (`List [`String "D"]))
172
assert_roundtrip pp_v v_to_yojson v_of_yojson
174
assert_roundtrip pp_v v_to_yojson v_of_yojson
175
(B 42) "[\"B\", 42]";
176
assert_roundtrip pp_v v_to_yojson v_of_yojson
177
(C (42, "foo")) "[\"C\", 42, \"foo\"]"
180
assert_roundtrip pp_r r_to_yojson r_of_yojson
181
{x=42; y="foo"} "{\"x\":42,\"y\":\"foo\"}"
183
#if OCAML_VERSION >= (4, 03, 0)
184
let test_recvar ctxt =
185
assert_roundtrip pp_rv rv_to_yojson rv_of_yojson
187
assert_roundtrip pp_rv rv_to_yojson rv_of_yojson
188
(RB 42) "[\"RB\", 42]";
189
assert_roundtrip pp_rv rv_to_yojson rv_of_yojson
190
(RC(42, "foo")) "[\"RC\", 42, \"foo\"]";
191
assert_roundtrip pp_rv rv_to_yojson rv_of_yojson
192
(RD{z="foo"}) "[\"RD\", {\"z\": \"foo\"}]"
196
lat : float [@key "Latitude"] ;
197
lon : float [@key "Longitude"] ;
199
[@@deriving yojson, show]
201
assert_roundtrip pp_geo geo_to_yojson geo_of_yojson
202
{lat=35.6895; lon=139.6917}
203
"{\"Latitude\":35.6895,\"Longitude\":139.6917}"
205
let test_field_err ctxt =
206
assert_equal ~printer:(show_error_or pp_geo)
207
(Result.Error "Test_ppx_yojson.geo.lat")
208
(geo_of_yojson (`Assoc ["Longitude", (`Float 42.0)]))
210
type id = Yojson.Safe.json [@@deriving yojson]
212
assert_roundtrip pp_json id_to_yojson id_of_yojson
216
| Tea of string [@name "tea"]
217
| Vodka [@name "vodka"]
218
[@@deriving yojson, show]
219
let test_custvar ctxt =
220
assert_roundtrip pp_custvar custvar_to_yojson custvar_of_yojson
221
(Tea "oolong") "[\"tea\", \"oolong\"]";
222
assert_roundtrip pp_custvar custvar_to_yojson custvar_of_yojson
226
[ `Tea of string [@name "tea"]
227
| `Beer of string * float [@name "beer"]
228
| `Vodka [@name "vodka"]
229
] [@@deriving yojson, show]
230
let test_custpvar ctxt =
231
assert_roundtrip pp_custpvar custpvar_to_yojson custpvar_of_yojson
232
(`Tea "earl_grey") "[\"tea\", \"earl_grey\"]";
233
assert_roundtrip pp_custpvar custpvar_to_yojson custpvar_of_yojson
234
(`Beer ("guinness", 3.3)) "[\"beer\", \"guinness\", 3.3]";
235
assert_roundtrip pp_custpvar custpvar_to_yojson custpvar_of_yojson
239
def : int [@default 42];
240
} [@@deriving yojson, show]
241
let test_default ctxt =
242
assert_roundtrip pp_default default_to_yojson default_of_yojson
245
type bidi = int [@@deriving show, to_yojson, of_yojson]
247
assert_roundtrip pp_bidi bidi_to_yojson bidi_of_yojson
250
let test_shortcut ctxt =
251
assert_roundtrip pp_i1 [%to_yojson: int] [%of_yojson: int]
255
nostrict_field : int;
257
[@@deriving show, yojson { strict = false }]
258
let test_nostrict ctxt =
259
assert_equal ~printer:(show_error_or pp_nostrict)
260
(Result.Ok { nostrict_field = 42 })
261
(nostrict_of_yojson (`Assoc ["nostrict_field", (`Int 42);
262
"some_other_field", (`Int 43)]))
266
type 'a opentype = .. [@@deriving yojson]
267
type 'a opentype += A of 'a | B of string list [@@deriving yojson]
270
type 'a opentype = .. [@@deriving yojson]
271
type 'a opentype += A of 'a | B of string list [@@deriving yojson]
273
type 'a Opentype.opentype +=
274
| C of 'a Opentype.opentype * float
277
let rec pp_opentype f fmt = function
278
A x -> Format.fprintf fmt "A(%s)" (f x)
279
| Opentype.B l -> Format.fprintf fmt "B(%s)" (String.concat ", " l)
281
Format.pp_print_string fmt "C(";
283
Format.fprintf fmt ", %f)" v
286
let test_opentype ctxt =
287
let pp_ot = pp_opentype string_of_int in
288
let to_yojson = Opentype.opentype_to_yojson i1_to_yojson in
289
let of_yojson = Opentype.opentype_of_yojson i1_of_yojson in
290
assert_roundtrip pp_ot to_yojson of_yojson
291
(Opentype.A 0) "[\"A\", 0]";
292
assert_roundtrip pp_ot to_yojson of_yojson
293
(Opentype.B ["one"; "two"]) "[\"B\", [ \"one\", \"two\"] ]";
294
assert_roundtrip pp_ot to_yojson of_yojson
295
(C (Opentype.A 42, 1.2)) "[\"C\", [\"A\", 42], 1.2]"
297
module Warnings = struct
301
[@@@ocaml.warning "@34"]
304
module M1 : sig type u [@@deriving yojson] end = struct
305
type internal = int list [@@deriving yojson]
306
type u = int list [@@deriving yojson]
308
(* the deriver for type [u] supposedly use the derivier of type
309
[internal]. Consider for instance the case where [u] is a map,
310
and internal is a list of bindings. *)
311
module M2 : sig type 'a u [@@deriving yojson] end = struct
312
type 'a internal = 'a list [@@deriving yojson]
313
type 'a u = 'a list [@@deriving yojson]
316
(* the deriver for type [u] supposedly use the derivier of type
317
[internal]. Consider for instance the case where [u] is a map,
318
and internal is a list of bindings. *)
319
(* module M1 : sig type 'a u [@@deriving yojson] end = struct *)
320
(* type 'a internal = .. [@@deriving yojson] (\* Triggers the warning *\) *)
321
(* type 'a internal += A of 'a | B of string list [@@deriving yojson] *)
322
(* type 'a u = 'a list [@@deriving yojson] *)
329
module TestShadowing = struct
334
type t = int list [@@deriving yojson]
336
module Array = struct
340
module Bytes = struct
341
let to_string () = ()
344
type v = bytes [@@deriving yojson]
349
module Test_recursive_polyvariant = struct
350
(* Regression test for
351
https://github.com/whitequark/ppx_deriving_yojson/issues/24 *)
352
type a = [ `B of string ]
353
[@@deriving of_yojson]
354
type b = [a | `C of b list]
355
[@@deriving of_yojson]
356
type c = [ a | b | `D of b list]
357
[@@deriving of_yojson]
358
let c_of_yojson yj : c Ppx_deriving_yojson_runtime.error_or = c_of_yojson yj
361
type 'a recursive1 = { lhs : string ; rhs : 'a }
362
and foo = unit recursive1
363
and bar = int recursive1
364
[@@deriving show, yojson]
366
let test_recursive ctxt =
367
assert_roundtrip (pp_recursive1 pp_i1)
368
(recursive1_to_yojson i1_to_yojson)
369
(recursive1_of_yojson i1_of_yojson)
370
{lhs="x"; rhs=42} "{\"lhs\":\"x\",\"rhs\":42}";
372
assert_roundtrip pp_foo foo_to_yojson foo_of_yojson
373
{lhs="x"; rhs=()} "{\"lhs\":\"x\",\"rhs\":null}" ;
375
assert_roundtrip pp_bar bar_to_yojson bar_of_yojson
376
{lhs="x"; rhs=42} "{\"lhs\":\"x\",\"rhs\":42}"
378
let test_int_redefined ctxt =
379
let module M = struct
380
type int = Break_things
382
let x = [%to_yojson: int] 1
385
let expected = `Int 1 in
386
assert_equal ~ctxt ~printer:show_json expected M.x
388
let suite = "Test ppx_yojson" >::: [
389
"test_unit" >:: test_unit;
390
"test_int" >:: test_int;
391
"test_int_edge" >:: test_int_edge;
392
"test_float" >:: test_float;
393
"test_bool" >:: test_bool;
394
"test_char" >:: test_char;
395
"test_string" >:: test_string;
396
"test_ref" >:: test_ref;
397
"test_option" >:: test_option;
398
"test_list" >:: test_list;
399
"test_array" >:: test_array;
400
"test_tuple" >:: test_tuple;
401
"test_ptyp" >:: test_ptyp;
402
"test_pvar" >:: test_pvar;
403
"test_var" >:: test_var;
404
"test_rec" >:: test_rec;
405
#if OCAML_VERSION >= (4, 03, 0)
406
"test_recvar" >:: test_recvar;
408
"test_key" >:: test_key;
409
"test_id" >:: test_id;
410
"test_custvar" >:: test_custvar;
411
"test_custpvar" >:: test_custpvar;
412
"test_field_err" >:: test_field_err;
413
"test_default" >:: test_default;
414
"test_bidi" >:: test_bidi;
415
"test_shortcut" >:: test_shortcut;
416
"test_nostrict" >:: test_nostrict;
417
"test_opentype" >:: test_opentype;
418
"test_recursive" >:: test_recursive;
419
"test_int_redefined" >:: test_int_redefined;
423
run_test_tt_main suite