@@ -42,8 +42,9 @@ module Of_json = struct
4242 [% expr
4343 Ppx_deriving_json_runtime. of_json_error ~json: x
4444 [% e
45- estring ~loc (sprintf " expected field %S to be present" n.txt)]]]]
46- )
45+ estring ~loc
46+ (sprintf " expected field %S to be present"
47+ n.txt)]]]] )
4748 in
4849 [% expr
4950 let fs = (Obj. magic [% e x] : [%t build_js_type ~loc fs] ) in
@@ -68,12 +69,19 @@ module Of_json = struct
6869 Ppx_deriving_json_runtime. of_json_msg_error
6970 [% e estring ~loc (sprintf " expected a JSON object" )]]
7071
71- let ensure_json_array_len ~loc n len x =
72+ let ensure_json_array_len ~loc ~ allow_any_constr ~ else_ n len x =
7273 [% expr
7374 if Stdlib. ( <> ) [% e len] [% e eint ~loc n] then
74- Ppx_deriving_json_runtime. of_json_msg_error ~json: [% e x]
75- [% e
76- estring ~loc (sprintf " expected a JSON array of length %i" n)]]
75+ [% e
76+ match allow_any_constr with
77+ | Some allow_any_constr -> allow_any_constr x
78+ | None ->
79+ [% expr
80+ Ppx_deriving_json_runtime. of_json_msg_error ~json: [% e x]
81+ [% e
82+ estring ~loc
83+ (sprintf " expected a JSON array of length %i" n)]]]
84+ else [% e else_]]
7785
7886 let derive_of_tuple derive t x =
7987 let loc = t.tpl_loc in
@@ -99,7 +107,7 @@ module Of_json = struct
99107 [% e ensure_json_object ~loc x];
100108 [% e build_record ~loc derive t.rcd_fields x Fun. id]]
101109
102- let derive_of_variant _derive t body x =
110+ let derive_of_variant _derive t ~ allow_any_constr body x =
103111 let loc = t.vrt_loc in
104112 [% expr
105113 if Js.Array. isArray [% e x] then
@@ -111,52 +119,75 @@ module Of_json = struct
111119 let tag = (Obj. magic tag : string ) in
112120 [% e body]
113121 else
114- Ppx_deriving_json_runtime. of_json_error ~json: [% e x]
115- " expected a non empty JSON array with element being a \
116- string"
122+ [% e
123+ match allow_any_constr with
124+ | Some allow_any_constr -> allow_any_constr x
125+ | None ->
126+ [% expr
127+ Ppx_deriving_json_runtime. of_json_error ~json: [% e x]
128+ " expected a non empty JSON array with element \
129+ being a string" ]]
117130 else
118- Ppx_deriving_json_runtime. of_json_error ~json: [% e x]
119- " expected a non empty JSON array"
131+ [% e
132+ match allow_any_constr with
133+ | Some allow_any_constr -> allow_any_constr x
134+ | None ->
135+ [% expr
136+ Ppx_deriving_json_runtime. of_json_error ~json: [% e x]
137+ " expected a non empty JSON array" ]]
120138 else
121- Ppx_deriving_json_runtime. of_json_error ~json: [% e x]
122- " expected a non empty JSON array" ]
139+ [% e
140+ match allow_any_constr with
141+ | Some allow_any_constr -> allow_any_constr x
142+ | None ->
143+ [% expr
144+ Ppx_deriving_json_runtime. of_json_error ~json: [% e x]
145+ " expected a non empty JSON array" ]]]
123146
124- let derive_of_variant_case derive make c next =
147+ let derive_of_variant_case derive make c ~ allow_any_constr next =
125148 match c with
126149 | Vcs_record (n , r ) ->
127150 let loc = n.loc in
128151 let n = Option. value ~default: n (vcs_attr_json_name r.rcd_ctx) in
129152 [% expr
130- if Stdlib. ( = ) tag [% e estring ~loc: n.loc n.txt] then (
131- [% e ensure_json_array_len ~loc 2 [% expr len] [% expr x]];
132- let fs = Js.Array. unsafe_get array 1 in
133- [% e ensure_json_object ~loc [% expr fs]];
153+ if Stdlib. ( = ) tag [% e estring ~loc: n.loc n.txt] then
134154 [% e
135- build_record ~loc derive r.rcd_fields [% expr fs] (fun e ->
136- make (Some e))])
155+ ensure_json_array_len ~loc ~allow_any_constr 2 [% expr len]
156+ [% expr x]
157+ ~else_:
158+ [% expr
159+ let fs = Js.Array. unsafe_get array 1 in
160+ [% e ensure_json_object ~loc [% expr fs]];
161+ [% e
162+ build_record ~loc derive r.rcd_fields [% expr fs]
163+ (fun e -> make (Some e))]]]
137164 else [% e next]]
138165 | Vcs_tuple (n , t ) ->
139166 let loc = n.loc in
140167 let n = Option. value ~default: n (vcs_attr_json_name t.tpl_ctx) in
141168 let arity = List. length t.tpl_types in
142169 [% expr
143- if Stdlib. ( = ) tag [% e estring ~loc: n.loc n.txt] then (
144- [% e ensure_json_array_len ~loc (arity + 1 ) [% expr len] [% expr x]];
170+ if Stdlib. ( = ) tag [% e estring ~loc: n.loc n.txt] then
145171 [% e
146- if Stdlib. ( = ) arity 0 then make None
147- else
148- make
149- (Some
150- (build_tuple ~loc derive 1 t.tpl_types [% expr array ]))])
172+ ensure_json_array_len ~loc ~allow_any_constr (arity + 1 )
173+ [% expr len] [% expr x]
174+ ~else_:
175+ (if Stdlib. ( = ) arity 0 then make None
176+ else
177+ make
178+ (Some
179+ (build_tuple ~loc derive 1 t.tpl_types
180+ [% expr array ])))]
151181 else [% e next]]
152182
183+ let is_allow_any_constr vcs =
184+ Ppx_deriving_json_common. vcs_attr_json_allow_any vcs
185+
153186 let deriving : Ppx_deriving_tools.deriving =
154187 deriving_of () ~name: " of_json"
155- ~error: (fun ~loc ->
156- [% expr Ppx_deriving_json_runtime. of_json_msg_error " invalid JSON" ])
157188 ~of_t: (fun ~loc -> [% type : Js.Json. t])
158- ~derive_of_tuple ~derive_of_record ~derive_of_variant
159- ~derive_of_variant_case
189+ ~is_allow_any_constr ~derive_of_tuple ~derive_of_record
190+ ~derive_of_variant ~ derive_of_variant_case
160191end
161192
162193module To_json = struct
@@ -194,13 +225,24 @@ module To_json = struct
194225 | Vcs_record (n , r ) ->
195226 let loc = n.loc in
196227 let n = Option. value ~default: n (vcs_attr_json_name r.rcd_ctx) in
197- let tag = [% expr (Obj. magic [% e estring ~loc: n.loc n.txt]: Js.Json.t )] in
228+ let tag =
229+ [% expr (Obj. magic [% e estring ~loc: n.loc n.txt] : Js.Json.t )]
230+ in
198231 let es = [ derive_of_record derive r es ] in
199232 as_json ~loc (pexp_array ~loc (tag :: es))
233+ | Vcs_tuple (_n , t ) when vcs_attr_json_allow_any t.tpl_ctx -> (
234+ match es with
235+ | [ x ] -> x
236+ | es ->
237+ failwith
238+ (sprintf " expected a tuple of length 1, got %i"
239+ (List. length es)))
200240 | Vcs_tuple (n , t ) ->
201241 let loc = n.loc in
202242 let n = Option. value ~default: n (vcs_attr_json_name t.tpl_ctx) in
203- let tag = [% expr (Obj. magic [% e estring ~loc: n.loc n.txt]: Js.Json.t )] in
243+ let tag =
244+ [% expr (Obj. magic [% e estring ~loc: n.loc n.txt] : Js.Json.t )]
245+ in
204246 let es = List. map2 t.tpl_types es ~f: derive in
205247 as_json ~loc (pexp_array ~loc (tag :: es))
206248
0 commit comments