ClojureScript - convert an arbitrary JavaScript object to a Clojure Script map

I am trying to convert a Javascript object to Clojure. However, I get the following error:

(js/console.log (js->clj e)) ;; has no effect (pprint (js->clj e)) ;; No protocol method IWriter.-write defined for type object: [object Geoposition] 

Yes, this object comes from the geolocation API. I suppose I need to extend IEncodeClojure and IWriter , but I don't know how to do this.

For example, adding the following:

 (extend-protocol IEncodeClojure Coordinates (-js->clj [x options] (println "HERE " x options))) 

Fixes an error loading my code: Uncaught TypeError: Cannot read property 'prototype' of undefined

+7
clojure clojurescript
source share
2 answers

js->clj only works for Object , everything with a custom constructor (see type ) will be returned as is.

see below: https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L9319

I suggest doing this instead:

 (defn jsx->clj [x] (into {} (for [k (.keys js/Object x)] [k (aget xk)]))) 
+8
source share

The accepted answer did not work for me with the javascript object window.performance.timing . This is because Object.keys() does not actually return the details for the PerformanceTiming object.

 (.keys js/Object (.-timing (.-performance js/window)) ; => #js[] 

This is despite the fact that PerformanceTiming details are really iterable using the vanilla JavaScript loop:

 for (a in window.performance.timing) { console.log(a); } // navigationStart // unloadEventStart // unloadEventEnd // ... 

The following is what I came up with to convert an arbitrary JavaScript object to a ClojureScript map. Pay attention to the use of two simple Google Closure features.

  • goog.typeOf wraps typeof , which is usually not available to us in ClojureScript. I use this to filter out the details that are functions.
  • goog.object.getKeys wraps for (prop in obj) {...} , creating the result of an array that we can reduce to a map.

Decision

 (defn obj->clj [obj] (-> (fn [result key] (let [v (aget obj key)] (if (= "function" (goog/typeOf v)) result (assoc result key v)))) (reduce {} (.getKeys goog/object obj)))) 
+4
source share

All Articles