27

I have some clojurescript that I want to interop with some javascript libraries. In my clojurescript code I do some analysis and come up with a list of maps. something like

[{:prop1 "value1" :prop2 "value2"}, {:prop1 "something else" :prop2 "etc"}...]

I need to pass this to a javascript functions as

[{prop1: "value1", prop2: "value2}, {..} ...]

I'm not sure how to return a javascript object form my clojurescript function though. Is there a way to serialize nested maps and lists to javascript objects. Or a way to create a new javascript object and then set properties on it?

Stephen Olsen
  • 713
  • 1
  • 6
  • 14

3 Answers3

49

Just for the sake of people looking for something similar.

The ClojureScript core now contains a clj->js function.

Kent Bull
  • 1,144
  • 3
  • 21
  • 41
Rodrigo Taboada
  • 2,727
  • 4
  • 24
  • 27
17

I found a function here

(defn clj->js
  "Recursively transforms ClojureScript maps into Javascript objects,
   other ClojureScript colls into JavaScript arrays, and ClojureScript
   keywords into JavaScript strings.

   Borrowed and updated from mmcgrana."
  [x]
  (cond
    (string? x) x
    (keyword? x) (name x)
    (map? x) (.-strobj (reduce (fn [m [k v]]
               (assoc m (clj->js k) (clj->js v))) {} x))
    (coll? x) (apply array (map clj->js x))
    :else x))

Does exactly what I needed. There is also the inverse function, namely js->clj in ClojureScript core.

fernandohur
  • 7,014
  • 11
  • 48
  • 86
Stephen Olsen
  • 713
  • 1
  • 6
  • 14
  • 3
    Your map conversion is exploiting an implementation detail of SOME cljs maps. It won't always work. Use this gist instead: https://gist.github.com/3153856 – Brian Jul 20 '12 at 23:35
  • @Brian -- looks like the `clj->js` in your gist doesn't actually use the `map->js` in your gist, unless I missed the intent? – Reb.Cabin Jun 09 '14 at 12:20
12

This works for me:

(defn clj->json
  [ds]
  (.stringify js/JSON (clj->js ds)))

usage:

(let [json (clj->json data-structure)]
  ;; do something with json
  )
Greg K
  • 10,770
  • 10
  • 45
  • 62
  • 2
    I like to pretty-print my json when running in test so it's more readable. To do this, add arguments to the .stringify line: `(.stringify js/JSON (clj->js ds) nil 2)` The nil is a replacer which will be unused, and the 2 means two spaces for each level of indent. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify – Mnebuerquo Aug 23 '17 at 15:48