-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error when encoding map with metadata on symbol key #47
Comments
I just ran into this issue using transit-clj in babashka writing maps with symbol keys. It appears that symbols contain line / column metadata by default. |
A workaround is to choose a different (longer than 1 character) tag for (ns workaround
(:require [cognitect.transit :as t])
(:import [java.io ByteArrayOutputStream]))
(def out (ByteArrayOutputStream. 2000))
(def w (t/writer out :json
{:handlers {clojure.lang.Symbol (t/write-handler "$$" t/nsed-name)}
:transform t/write-meta}))
(t/write w {(with-meta 'SYMBOL {:foo 'bar}) 'val})
(def ba (.toByteArray out))
(def transit (String. ba))
(prn transit)
;;=> "[\"~#cmap\",[[\"~#with-meta\",[[\"~#$$\",\"SYMBOL\"],[\"^ \",\"~:foo\",[\"^2\",\"bar\"]]]],[\"^2\",\"val\"]]]"
(require '[clojure.java.io :as io])
(def r (t/reader (io/input-stream ba) :json
{:handlers (t/read-handler-map {"$$" (t/read-handler symbol)})}))
(prn (map meta (keys (t/read r))))
;;=> ({:foo bar}) I'm not entirely sure what a proper solution for this is, but I noticed there are several |
The map with symbols having metadata passes a |
I've got another workaround here which surfaces another interesting bit. When using a conditional tag that returns a custom tag when there's metadata on the symbol, but a single dollar when there's not, the transit appears normal and the special tag doesn't even appear. I'm not sure why this workaround works, but the interesting bit is that it preserves the original transit format which can be read without any modifications on consumers. (ns workaround
(:require [cognitect.transit :as t]
[clojure.java.io :as io])
(:import [java.io ByteArrayOutputStream]))
(defn obj->str [v]
(let [out (ByteArrayOutputStream. 2000)
w (t/writer out :json
{:handlers {clojure.lang.Symbol
(t/write-handler (fn [v]
(if (meta v)
"<SPECIAL_TAG>"
"$"))
t/nsed-name)}
:transform t/write-meta})]
(t/write w v)
(String. (.toByteArray out))))
;; look ma, no special read handler
(defn str->obj [s]
(let [rdr (t/reader (io/input-stream (.getBytes s)) :json)
v (t/read rdr)]
v))
(let [map-w-symbol-meta {(with-meta 'SYMBOL {:foo 'bar}) 'val}
transit-w-meta (obj->str map-w-symbol-meta)
v (str->obj transit-w-meta)]
(prn transit-w-meta)
;;=> "[\"~#cmap\",[[\"~#with-meta\",[[\"~#$$\",\"SYMBOL\"],[\"^ \",\"~:foo\",[\"^2\",\"bar\"]]]],[\"^2\",\"val\"]]]"
(prn v) ;;=> {SYMBOL val}
(prn (map meta (keys v))) ;;=> ({:foo bar})
)
(let [map-wo-symbol-meta {'SYMBOL 'val}
transit-w-meta (obj->str map-wo-symbol-meta)
v (str->obj transit-w-meta)]
(prn transit-w-meta)
;;=> "[\"^ \",\"~$SYMBOL\",\"~$val\"]"
(prn v) ;;=> {SYMBOL val}
(prn (map meta (keys v))) ;;=> (nil)
) |
…g resolution when present. This handles the case where a transformer may convert an object into a form that the marhsaling phase may not be able to handle. This bifurcation between the classifying tag and the marshaled form was specifically causing issues where symbol map keys with metadata did not marshal into a stringable form but was classified as stringable earlier in the write phase.
We have a fix for this prepped that you can try, it uses a git dep for transit-java that requires prepping (there is no change in transit-clj): In your deps.edn: {:deps
{com.cognitect/transit-clj {:mvn/version "1.0.324"}
com.cognitect/transit-java {:git/url "https://github.com/cognitect/transit-java.git" :git/sha "f84ca6290b7a0489a8671bc96bd76ede8b391415"}}} And then you will need to prep with:
And then you should be able to test this fix. Please let us know what you find! |
@puredanger @fogus looks good to me running first tests on the repl, thank you! Will also plug this into our CI and report back if we encounter any other issues. |
Released in transit-java 1.0.362 and transit-clj 1.0.329 |
transit-clj
errors when trying to encode a map with a symbol key with metadata on it:I think the issue is that transit should pick a
cmap
for a symbol with metadata on it.The same works with transit-cljs:
The text was updated successfully, but these errors were encountered: