package query-json

  1. Overview
  2. Docs

Source file Json.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
include Yojson.Safe
include Yojson.Safe.Util

type json = t

let parse_string str =
  try Ok (Yojson.Safe.from_string str) with
  | Yojson.Json_error msg -> Error ("JSON parse error: " ^ msg)
  | e -> Error (Printexc.to_string e ^ " There was an error reading the string")

let parse_file file =
  try Ok (Yojson.Safe.from_file file) with
  | Yojson.Json_error msg -> Error ("JSON parse error: " ^ msg)
  | e -> Error (Printexc.to_string e ^ " There was an error reading the file")

let parse_channel channel =
  try Ok (Yojson.Safe.from_channel channel) with
  | Yojson.Json_error msg -> Error ("JSON parse error: " ^ msg)
  | e ->
      Error
        (Printexc.to_string e
       ^ " There was an error reading from standard input")

let encode str =
  let buf = Buffer.create (String.length str * 5 / 4) in
  for i = 0 to String.length str - 1 do
    match str.[i] with
    | '\\' -> Buffer.add_string buf {|\\|}
    | '"' -> Buffer.add_string buf {|\"|}
    | '\n' -> Buffer.add_string buf {|\n|}
    | '\t' -> Buffer.add_string buf {|\t|}
    | '\r' -> Buffer.add_string buf {|\r|}
    | '\b' -> Buffer.add_string buf {|\b|}
    | ('\000' .. '\031' | '\127') as c ->
        Printf.bprintf buf "\\u%04X" (Char.code c)
    | c -> Buffer.add_char buf c
  done;
  Buffer.contents buf

module Make_format (Chalk : sig
  val green : string -> string
  val blue : string -> string
  val bold : string -> string
end) (Config : sig
  val summarize : bool
end) =
struct
  let quotes str = "\"" ^ str ^ "\""

  let rec to_easy_format = function
    | `Null -> Easy_format.Atom (Chalk.green "null", Easy_format.atom)
    | `Bool b ->
        Easy_format.Atom (Chalk.green (Bool.to_string b), Easy_format.atom)
    | `Int i ->
        Easy_format.Atom (Chalk.green (Int.to_string i), Easy_format.atom)
    | `Float f ->
        let float_to_string float =
          if Stdlib.Float.equal (Stdlib.Float.round float) float then
            float |> Float.to_int |> Int.to_string
          else Printf.sprintf "%g" float
        in
        Easy_format.Atom (Chalk.green (float_to_string f), Easy_format.atom)
    | `String s ->
        Easy_format.Atom (Chalk.green (quotes (encode s)), Easy_format.atom)
    | `Intlit s -> Easy_format.Atom (Chalk.green s, Easy_format.atom)
    | `List [] -> Easy_format.Atom ("[]", Easy_format.atom)
    | `List (l : json list) ->
        Easy_format.List
          (("[", ",", "]", Easy_format.list), List.map to_easy_format l)
    | `Assoc [] -> Easy_format.Atom ("{}", Easy_format.atom)
    | `Assoc (l : (string * json) list) ->
        Easy_format.List (("{", ",", "}", Easy_format.list), List.map item l)

  and item (name, json) =
    let s =
      Printf.sprintf "%s:" (name |> encode |> quotes |> Chalk.blue |> Chalk.bold)
    in
    let value =
      if Config.summarize then Easy_format.Atom ("...", Easy_format.atom)
      else to_easy_format json
    in
    Easy_format.Label
      ((Easy_format.Atom (s, Easy_format.atom), Easy_format.label), value)
end

let to_string (json : json) ~colorize ~summarize =
  let module Chalk = Chalk.Make (struct
    let disable = not colorize
  end) in
  let module Format =
    Make_format
      (Chalk)
      (struct
        let summarize = summarize
      end)
  in
  Easy_format.Pretty.to_string (Format.to_easy_format json)