I am trying to convert a Javascript object to a 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 that I have to extend IEncodeClojure and IWriter, but I have no clue how.
For instance adding the following :
(extend-protocol IEncodeClojure
Coordinates
(-js->clj [x options]
(println "HERE " x options)))
Yields an error when loading my code : Uncaught TypeError: Cannot read property 'prototype' of undefined
The accepted answer wasn't working for me with the javascript object window.performance.timing. This is because Object.keys() doesn't actually return the props for the PerformanceTiming object.
(.keys js/Object (.-timing (.-performance js/window))
; => #js[]
This is despite the fact that the props of PerformanceTiming are indeed iterable with a 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. Note the use of two simple Google Closure functions.
goog.typeOf wraps typeof, which isn't normally accessible to us in ClojureScript. I use this to filter out props which are functions.goog.object.getKeys wraps for (prop in obj) {...}, building up an array result which we can reduce into a map.(defn obj->clj
[obj]
(-> (fn [result key]
(let [v (goog.object/get obj key)]
(if (= "function" (goog/typeOf v))
result
(assoc result key v))))
(reduce {} (.getKeys goog/object obj))))
Update: This solution will work for nested maps.
(defn obj->clj
[obj]
(if (goog.isObject obj)
(-> (fn [result key]
(let [v (goog.object/get obj key)]
(if (= "function" (goog/typeOf v))
result
(assoc result key (obj->clj v)))))
(reduce {} (.getKeys goog/object obj)))
obj))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With