Skip to content

Instantly share code, notes, and snippets.

@rnewman
Created September 21, 2016 20:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rnewman/0de1869fdd1667f6b4960cd49fa6d813 to your computer and use it in GitHub Desktop.
Save rnewman/0de1869fdd1667f6b4960cd49fa6d813 to your computer and use it in GitHub Desktop.
js->clj that works across contexts
(defn cljify
"Does what `(js->clj o :keywordize-keys true) is supposed to do, but works
in environments with more than one context (e.g., web browsers).
See <http://dev.clojure.org/jira/browse/CLJS-439?focusedCommentId=43909>.
Note that Date instances are passed through."
[o]
(cond
(nil? o)
nil
;; Primitives.
(or
(true? o)
(false? o)
(number? o)
(string? o)
;; Dates are passed through.
(not (nil? (aget (aget o "__proto__") "getUTCMilliseconds"))))
o
;; Array.
(.isArray js/Array o)
(let [n (.-length o)]
(loop [i 0
acc (transient [])]
(if (< i n)
(recur (inc i) (conj! acc (cljify (aget o i))))
(persistent! acc))))
;; Object.
(not (nil? (aget (aget o "__proto__") "hasOwnProperty")))
(let [a (.keys js/Object o)
n (.-length a)]
(loop [i 0
acc (transient {})]
(if (< i n)
(let [key (aget a i)]
(recur (inc i) (assoc! acc
(keyword key)
(cljify (aget o key)))))
(persistent! acc))))
:else o))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment