(* emit_json.ml *) module T = Template let escape_string s = let b = Buffer.create (String.length s + 8) in Buffer.add_char b '"'; String.iter (fun c -> match c with | '"' -> Buffer.add_string b "\\\"" | '\\' -> Buffer.add_string b "\\\\" | '\n' -> Buffer.add_string b "\\n" | '\r' -> Buffer.add_string b "\\r" | '\t' -> Buffer.add_string b "\\t" | c when Char.code c < 0x20 -> Buffer.add_string b (Printf.sprintf "\\u%04x" (Char.code c)) | c -> Buffer.add_char b c) s; Buffer.add_char b '"'; Buffer.contents b (* Emit the view tree directly. Bools stay bools; everything else is a string, an array or an object -- there are no numbers in the view, deliberately, so a consumer never has to guess whether "week" is 2 or "2". *) let rec write b (v : T.value) = match v with | T.Str s -> Buffer.add_string b (escape_string s) | T.Bool x -> Buffer.add_string b (if x then "true" else "false") | T.List l -> Buffer.add_char b '['; List.iteri (fun i x -> if i > 0 then Buffer.add_char b ','; write b x) l; Buffer.add_char b ']' | T.Obj kvs -> Buffer.add_char b '{'; List.iteri (fun i (k, x) -> if i > 0 then Buffer.add_char b ','; Buffer.add_string b (escape_string k); Buffer.add_char b ':'; write b x) kvs; Buffer.add_char b '}' let year v = let b = Buffer.create (64 * 1024) in write b v; Buffer.add_char b '\n'; Buffer.contents b