tailrecursion / cljson

Clojure/ClojureScript library for accelerated browser data deserialization
62 stars 4 forks source link

Support for Clojurescript records? #9

Closed kendagriff closed 10 years ago

kendagriff commented 10 years ago

Does cljson not work for Clojurescript records?

(defrecord Person [name])
(clj->cljson (Person. "Bob"))
(binding [*data-readers* {'game2.core.Person map->Person}] (cljson->clj [\"game2.core.Person\",[\"m\",[\"k\",\"name\"],\"Bob\"]]"))

Returns:

"Error evaluating:" (binding [*data-readers* {(quote game2.core.Person) map->Person}] (cljson->clj "[\"game2.core.Person\",[\"m\",[\"k\",\"name\"],\"Bob\"]]")
) :as "var _STAR_data_readers_STAR_15555_15556 = game2.core._STAR_data_readers_STAR_;try{game2.core._STAR_data_readers_STAR_ = new cljs.core.PersistentArrayMa
p(null, 1, [new cljs.core.Symbol(null,\"game2.core.Person\",\"game2.core.Person\",1938104303,null),game2.core.map__GT_Person], null);\ntailrecursion.cljson.cl
json__GT_clj.call(null,\"[\\\"game2.core.Person\\\",[\\\"m\\\",[\\\"k\\\",\\\"name\\\"],\\\"Bob\\\"]]\");\n}finally {game2.core._STAR_data_readers_STAR_ = _ST
AR_data_readers_STAR_15555_15556;\n}"
org.mozilla.javascript.JavaScriptException: Error: No reader function for tag 'game2.core.Person'. (file:/Users/kendallbuchanan/Documents/Work/Banzai/Apps/gam
e/game2/.repl/tailrecursion/cljson.js#249)
        at file:/Users/kendallbuchanan/Documents/Work/Banzai/Apps/game/game2/.repl/tailrecursion/cljson.js:249 (decode_tagged)
        at file:/Users/kendallbuchanan/Documents/Work/Banzai/Apps/game/game2/.repl/tailrecursion/cljson.js:263 (decode)
        at file:/Users/kendallbuchanan/Documents/Work/Banzai/Apps/game/game2/.repl/tailrecursion/cljson.js:41 (cljson__GT_clj)
        at <cljs repl>:2 (anonymous)
        at <cljs repl>:1 (anonymous)
        at <cljs repl>:1
nil

This seems fairly basic... am I missing anything?

alandipert commented 10 years ago

So, a couple things:

  1. clj->cljson returns a string, not a ClojureScript vector or a JavaScript object (although it sure does look like one when printed). So, you'd only want to call cljson->clj with a string argument.
  2. There isn't a cljs.core/*data-readers*. ClojureScript leans on Clojure's reader for compilation. However, a ClojureScript reader implementation is supplied in cljs.reader.

Here's an example ClojureScript namespace to accomplish what you want:

(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} 

Please close this if your question is answered. Thanks!

kendagriff commented 10 years ago

Yes, that was a huge help! This would have helped in the README; shall I submit a pull request?

alandipert commented 10 years ago

That would be great, thanks!