/
yojson_conv.ml
234 lines (203 loc) · 6.96 KB
/
yojson_conv.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
open StdLabels
open MoreLabels
open! Yojson
type t = Yojson.Safe.t
let yojson_of_unit () : t = `Null
let yojson_of_bool b : t = `Bool b
let yojson_of_string str : t = `String str
let yojson_of_bytes bytes : t = `String (Bytes.to_string bytes)
let yojson_of_char c : t = `String (String.make 1 c)
let yojson_of_int n : t = `Int n
let yojson_of_float n : t = `Float n
let yojson_of_int32 (n : Int32.t) : t = `Intlit (Int32.to_string n)
let yojson_of_int64 (n : Int64.t) : t = `Intlit (Int64.to_string n)
let yojson_of_nativeint n : t = `Intlit (Nativeint.to_string n)
let yojson_of_ref yojson_of__a rf = yojson_of__a !rf
let yojson_of_lazy_t yojson_of__a lv = yojson_of__a (Lazy.force lv)
let yojson_of_option yojson_of__a = function
| Some x -> yojson_of__a x
| None -> `Null
;;
let yojson_of_pair yojson_of__a yojson_of__b (a, b) =
`List [ yojson_of__a a; yojson_of__b b ]
;;
let yojson_of_triple yojson_of__a yojson_of__b yojson_of__c (a, b, c) =
`List [ yojson_of__a a; yojson_of__b b; yojson_of__c c ]
;;
(* List.rev (List.rev_map ...) is tail recursive, the OCaml standard
library List.map is NOT. *)
let yojson_of_list yojson_of__a lst = `List (List.rev (List.rev_map ~f:yojson_of__a lst))
let yojson_of_array yojson_of__a ar =
let lst_ref = ref [] in
for i = Array.length ar - 1 downto 0 do
lst_ref := yojson_of__a ar.(i) :: !lst_ref
done;
`List !lst_ref
;;
let yojson_of_hashtbl yojson_of_key yojson_of_val htbl =
let coll ~key:k ~data:v acc = `List [ yojson_of_key k; yojson_of_val v ] :: acc in
`List (Hashtbl.fold htbl ~init:[] ~f:coll)
;;
let yojson_of_opaque _ = `String "<opaque>"
let yojson_of_fun _ = `String "<fun>"
exception Of_yojson_error of exn * t
let record_check_extra_fields = ref true
let of_yojson_error_exn exc yojson = raise (Of_yojson_error (exc, yojson))
let of_yojson_error what yojson = raise (Of_yojson_error (Failure what, yojson))
let unit_of_yojson yojson =
match yojson with
| `Null -> ()
| _ -> of_yojson_error "unit_of_yojson: `Null needed" yojson
;;
let bool_of_yojson yojson =
match yojson with
| `Bool v -> v
| _ -> of_yojson_error "bool_of_yojson: true/false needed" yojson
;;
let string_of_yojson yojson =
match yojson with
| `String str -> str
| _ -> of_yojson_error "string_of_yojson: string needed" yojson
;;
let bytes_of_yojson yojson =
match yojson with
| `String str -> Bytes.of_string str
| _ -> of_yojson_error "bytes_of_yojson: string needed" yojson
;;
let char_of_yojson yojson =
match yojson with
| `String str ->
if String.length str <> 1
then of_yojson_error "char_of_yojson: string must contain one character only" yojson;
str.[0]
| _ -> of_yojson_error "char_of_yojson: string of size one needed" yojson
;;
let int_of_yojson yojson =
match yojson with
| `Int v -> v
| _ -> of_yojson_error "int_of_yojson: integer needed" yojson
;;
let float_of_yojson yojson =
match yojson with
| `Float v -> v
| `Int i -> float_of_int i
| `Intlit str -> float_of_string str
| _ -> of_yojson_error "float_of_yojson: float needed" yojson
;;
let int32_of_yojson yojson =
match yojson with
| `Intlit str -> Int32.of_string str
| `Int v -> Int32.of_int v
| _ -> of_yojson_error "int32_of_yojson: integer needed" yojson
;;
let int64_of_yojson yojson =
match yojson with
| `Intlit str -> Int64.of_string str
| `Int v -> Int64.of_int v
| _ -> of_yojson_error "int64_of_yojson: integer needed" yojson
;;
let nativeint_of_yojson yojson =
match yojson with
| `Intlit str -> Nativeint.of_string str
| `Int v -> Nativeint.of_int v
| _ -> of_yojson_error "nativeint_of_yojson: integer needed" yojson
;;
let ref_of_yojson a__of_yojson yojson = ref (a__of_yojson yojson)
let lazy_t_of_yojson a__of_yojson yojson = Lazy.from_val (a__of_yojson yojson)
let option_of_yojson a__of_yojson yojson =
match yojson with
| `Null -> None
| el -> Some (a__of_yojson el)
;;
let pair_of_yojson a__of_yojson b__of_yojson yojson =
match yojson with
| `List [ a_yojson; b_yojson ] ->
let a = a__of_yojson a_yojson in
let b = b__of_yojson b_yojson in
a, b
| _ -> of_yojson_error "pair_of_yojson: invalid format" yojson
;;
let triple_of_yojson a__of_yojson b__of_yojson c__of_yojson yojson =
match yojson with
| `List [ a_yojson; b_yojson; c_yojson ] ->
let a = a__of_yojson a_yojson in
let b = b__of_yojson b_yojson in
let c = c__of_yojson c_yojson in
a, b, c
| _ -> of_yojson_error "triple_of_yojson: invalid format" yojson
;;
let list_of_yojson a__of_yojson yojson =
match yojson with
| `List lst ->
let rev_lst = List.rev_map lst ~f:a__of_yojson in
List.rev rev_lst
| _ -> of_yojson_error "list_of_yojson: list needed" yojson
;;
let array_of_yojson a__of_yojson yojson =
match yojson with
| `List [] -> [||]
| `List (h :: t) ->
let len = List.length t + 1 in
let res = Array.make len (a__of_yojson h) in
let rec loop i = function
| [] -> res
| h :: t ->
res.(i) <- a__of_yojson h;
loop (i + 1) t
in
loop 1 t
| _ -> of_yojson_error "array_of_yojson: list needed" yojson
;;
let hashtbl_of_yojson key_of_yojson val_of_yojson yojson =
match yojson with
| `List lst ->
let htbl = Hashtbl.create 0 in
let act = function
| `List [ k_yojson; v_yojson ] ->
Hashtbl.add htbl ~key:(key_of_yojson k_yojson) ~data:(val_of_yojson v_yojson)
| _ -> of_yojson_error "hashtbl_of_yojson: tuple list needed" yojson
in
List.iter lst ~f:act;
htbl
| _ -> of_yojson_error "hashtbl_of_yojson: list needed" yojson
;;
let opaque_of_yojson yojson =
of_yojson_error "opaque_of_yojson: cannot convert opaque values" yojson
;;
let fun_of_yojson yojson =
of_yojson_error "fun_of_yojson: cannot convert function values" yojson
;;
module Primitives = struct
let yojson_of_array = yojson_of_array
let array_of_yojson = array_of_yojson
let yojson_of_bool = yojson_of_bool
let bool_of_yojson = bool_of_yojson
let yojson_of_char = yojson_of_char
let char_of_yojson = char_of_yojson
let yojson_of_float = yojson_of_float
let float_of_yojson = float_of_yojson
let yojson_of_int = yojson_of_int
let int_of_yojson = int_of_yojson
let yojson_of_int32 = yojson_of_int32
let int32_of_yojson = int32_of_yojson
let yojson_of_int64 = yojson_of_int64
let int64_of_yojson = int64_of_yojson
let yojson_of_list = yojson_of_list
let list_of_yojson = list_of_yojson
let yojson_of_nativeint = yojson_of_nativeint
let nativeint_of_yojson = nativeint_of_yojson
let yojson_of_option = yojson_of_option
let option_of_yojson = option_of_yojson
let yojson_of_ref = yojson_of_ref
let ref_of_yojson = ref_of_yojson
let yojson_of_string = yojson_of_string
let string_of_yojson = string_of_yojson
let yojson_of_bytes = yojson_of_bytes
let bytes_of_yojson = bytes_of_yojson
let yojson_of_unit = yojson_of_unit
let unit_of_yojson = unit_of_yojson
let yojson_of_lazy_t = yojson_of_lazy_t
let lazy_t_of_yojson = lazy_t_of_yojson
let yojson_of_hashtbl = yojson_of_hashtbl
let hashtbl_of_yojson = hashtbl_of_yojson
end