As of 10/20/2015, this library is in maintenance mode. We will continue to review pull requests for bug fixes, but for new projects, consider using transit-cljs instead. While built on the same idea of using JSON as the transport format, it is probably more efficient and supports interchange between a multitude of platforms beyond Clojure and ClojureScript.
We have been using Transit for the past few months ourselves in Hoplon and it has been a good experience so far.
Use cljson to send data between Clojure and ClojureScript applications using JSON as the data transfer format. The cljson library has implementations for Clojure and ClojureScript and supports all the data types that ClojureScript supports, including tagged literals and metadata.
Artifacts are published on Clojars.
There are two functions exported by this library: clj->cljson
and
cljson->clj
. They convert Clojure data to and from JSON strings.
user=> (require '[tailrecursion.cljson :refer [clj->cljson cljson->clj]])
nil
user=> (clj->cljson [1 2 3])
"[\"v\",1,2,3]"
user=> (cljson->clj "[\"v\",1,2,3]")
[1 2 3]
user=> (clj->cljson '(1 2 3))
"[\"l\",1,2,3]"
user=> (cljson->clj "[\"l\",1,2,3]")
(1 2 3)
user=> (clj->cljson [(java.util.Date.) {[1 2 3] :foo 'bar #{"bar"}}])
"[\"v\",[\"inst\",\"2013-06-24T17:34:04.183-00:00\"],[\"m\",[\"v\",1,2,3],[\"k\",\"foo\"],[\"y\",\"bar\"],[\"s\",\"bar\"]]]"
user=> (cljson->clj "[\"v\",[\"inst\",\"2013-06-24T17:34:04.183-00:00\"],[\"m\",[\"v\",1,2,3],[\"k\",\"foo\"],[\"y\",\"bar\"],[\"s\",\"bar\"]]]")
[#inst "2013-06-24T17:34:04.183-00:00" {[1 2 3] :foo, bar #{"bar"}}]
user> (defrecord Person [name])
user.Person
user> (clj->cljson (Person. "Bob"))
"[\"user.Person\",[\"m\",[\"k\",\"name\"],\"Bob\"]]"
user> (binding [*data-readers* {'user.Person map->Person}] (cljson->clj "[\"user.Person\",[\"m\",[\"k\",\"name\"],\"Bob\"]]"))
#user.Person{:name "Bob"}
Cljson provides the EncodeTagged
protocol which can be extended to user types
and records. This protocol is used to transform a Clojure/ClojureScript thing
into JSON-ready data.
If a type does not satisfy this protocol then cljson will use the core printer to obtain a printed representation of the thing. If the printed representation is a tagged literal then the data part is reread and converted to JSON-ready data.
Reading of tagged literals is done via the normal tagged literal mechanisms built into Clojure and ClojureScript.
Have a look at cljson.clj and cljson.cljs to see examples of this.
Bind *print-meta*
to true
to have metadata included in the JSON output.
Unlike clojure.core
, ClojureScript lacks a *data-readers*
dynamic var. Instead, use cljs.reader's register-tag-parser!
function to declare constructors for records and types:
(ns example
(:require [tailrecursion.cljson :refer [clj->cljson cljson->clj]]
[cljs.reader :refer [register-tag-parser!]]))
(defrecord Person [name])
(register-tag-parser! "example.Person" map->Person)
(print (cljson->clj (clj->cljson (Person. "Bob")))) ;=> #example.Person{:name Bob}
Copyright © 2013 Alan Dipert and Micha Niskin
Distributed under the Eclipse Public License, the same as Clojure.