p2p-cljs / src / ird / p2p / impl / json.cljs
222 words
 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
(ns ird.p2p.impl.json
  "JSON on the wire, serialized like JavaScript's JSON.stringify: no
  whitespace, object keys in insertion order, integers without a fraction.
  `stringify` walks ClojureScript data itself so that a map's own key order
  (insertion order for maps up to eight keys) reaches the wire exactly —
  the sealed envelope vectors depend on it. `parse` never throws.

  Internal interop namespace."
  (:require [clojure.string :as str]))

(declare stringify)

(defn- key-name [k]
  (cond (keyword? k) (if-let [ns (namespace k)] (str ns "/" (name k)) (name k))
        (symbol? k) (str k)
        :else (str k)))

(defn stringify
  "Compact JSON text of V (maps, vectors/seqs, strings, numbers, booleans,
  nil, keywords as their names)."
  [v]
  (cond
    (nil? v) "null"
    (string? v) (js/JSON.stringify v)
    (keyword? v) (js/JSON.stringify (key-name v))
    (number? v) (js/JSON.stringify v)
    (boolean? v) (if v "true" "false")
    (map? v) (str "{" (str/join "," (map (fn [[k x]] (str (js/JSON.stringify (key-name k)) ":" (stringify x))) v)) "}")
    (or (sequential? v) (set? v)) (str "[" (str/join "," (map stringify v)) "]")
    :else (js/JSON.stringify (clj->js v))))

(defn parse
  "Parse JSON TEXT into ClojureScript data with keyword keys; nil when the
  text is not JSON (never throws)."
  [text]
  (when (string? text)
    (try (js->clj (js/JSON.parse text) :keywordize-keys true)
         (catch :default _ nil))))

(defn parse-strings
  "Like `parse` but keeps object keys as strings."
  [text]
  (when (string? text)
    (try (js->clj (js/JSON.parse text))
         (catch :default _ nil))))

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/p2p-cljs.git