How to map clojure code to and from JSON? How to map clojure code to and from JSON? json json

How to map clojure code to and from JSON?


As mikera suggested, clojure.contrib.json/write-json will convert not only primitive types, but Clojure's ISeqs and Java's Maps, Collections and Arrays, too. This should cover most of your code (seen as data), but in the event you want to write anything fancier, it's easy to extend the JSON writer, by mimicking out Stuart Sierra's source code (see here):

(defn- write-json-fancy-type [x #^PrintWriter out]    (write-json-string (str x) out)) ;; or something useful here!(extend your-namespace.FancyType clojure.contrib.json/Write-JSON    {:write-json write-json-fancy-type})

This is assuming you don't need to store computed bytecode, or captured closures. This would be an entirely different game, significantly harder. But since most Clojure code (like most Lisp's) can be seen as a tree/forest of S-Expressions, you should be OK.

Parsing out JSON back to the data can be done with clojure.contrib.json/read-json (take a short time to look at the options on its definition, you may want to use them). After that, eval may be your best friend.


If you want to use JSON as a representation, I'd strongly suggest using clojure.contrib.json, which already does the job of converting Clojure data structures to JSON pretty seamlessly.

No point reinventing the wheel :-)

I've used it pretty successfully in my current Clojure project. If it doesn't do everything you want, then you can always contribute a patch to improve it!


I think your idea is sound, but I'd simplify the handling of collections by using tagged arrays (["list", …], ["vector", …]) instead. Apart from that, I wouldn't change the implementation strategy.

I like your idea and to code in Clojure, so I took a stab at implementing your code-to-json (with the above suggestion incorporated) at https://gist.github.com/3219854.

This is the output it generates:

(code-to-json example-code); => ["list" ["list" "'ns" "'bz.json.app" ["list" ":use" ["list" "'ring.middleware" "'file"]]] ["list" "'defn" "'hello" ["vector" "'req"] {":status" 200, ":headers" {"Content-Type" "text/plain"}, ":body" "Hello World!"}] ["list" "'def" "'app" ["list" "'wrap-file" "'hello" "public"]]]

json-to-code is left as an exercise for the reader. ;)