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
type json =
  | Unit
  | Bool of bool
  | Float of float
  | String of string
  | Array of json list
  | Object of (string * json) list

exception Escape of ((int * int) * (int * int)) * Jsonm.error

let json_of_src ?encoding (src : [ `Channel of in_channel | `String of string ])
    =
  let dec d =
    match Jsonm.decode d with
    | `Lexeme l -> l
    | `Error e -> raise (Escape (Jsonm.decoded_range d, e))
    | `End | `Await -> assert false
  in
  let rec value v k d =
    match v with
    | `Os -> obj [] k d
    | `As -> arr [] k d
    | `Null -> k Unit d
    | `Bool b -> k (Bool b) d
    | `String s -> k (String s) d
    | `Float f -> k (Float f) d
    | _ -> assert false
  and arr vs k d =
    match dec d with
    | `Ae -> k (Array (List.rev vs)) d
    | v -> value v (fun v -> arr (v :: vs) k) d
  and obj ms k d =
    match dec d with
    | `Oe -> k (Object (List.rev ms)) d
    | `Name n -> value (dec d) (fun v -> obj ((n, v) :: ms) k) d
    | _ -> assert false
  in
  let d = Jsonm.decoder ?encoding src in
  try Ok (value (dec d) (fun v _ -> v) d) with Escape (r, e) -> Error (r, e)

exception Found of json

let rec find key = function
  | Unit | Bool _ | Float _ | String _ -> None
  | Array l -> begin
    try
      List.iter
        (fun v -> match find key v with None -> () | Some v -> raise (Found v))
        l;
      None
    with Found v -> Some v
  end
  | Object l -> (
    try
      List.iter (fun (k, v) -> if k = key then raise (Found v)) l;
      None
    with Found v -> Some v )

let find_string key v =
  match find key v with Some (String f) -> Some f | _ -> None

let find_obj key v =
  match find key v with Some (Object o) -> Some o | _ -> None