Welcome! Please see the About page for a little more info on how this works.

+2 votes
in data.json by
retagged by

Internally, clojure.data.json/write calls name on instances of clojure.lang.Named wherever it encounters them, which strips the namespace:

(json/write {:foo/bar :baz/bork}
            *out*
            :escape-slash false)
;; => {"bar":"bork"}

The clojure.data.json/write function provides the options :key-fn and :value-fn for changing this (or any other) behavior on map keys and values:

(json/write {:foo/bar :baz/bork}
            *out*
            :escape-slash false
            :key-fn (comp str symbol)
            :value-fn (fn [k v] (if (instance? clojure.lang.Named v)
                                  (str (symbol v))
                                  v)))
;; => {"foo/bar":"baz/bork"}

But it doesn't work in other contexts (and, per the docstring, is not meant to):

(json/write {:foo/bar [:baz/bork]}
            *out*
            :escape-slash false
            :key-fn (comp str symbol)
            :value-fn (fn [k v] (if (instance? clojure.lang.Named v)
                                  (str (symbol v))
                                  v)))
;; => {"foo/bar":["bork"]}

The only available mechanism for changing this behavior in all contexts is to extend the JSONWriter protocol, but this would change the behavior globally. It would be helpful if an option were available to preserve namespaces in all contexts, or to override how a given type is written without changing it globally.

by
edited by
I just hit the exact same issue.

I'm also worried about overriding the default behaviour, just in case some other lib (eg. Datomic Cloud) depends on it.

I did try to override though, based on the default implementation and I haven't experienced any issues so far:

    (defn- write-named [x out options]
      (json/-write (kw->sym->str x) out options))
    
    (extend clojure.lang.Named json/JSONWriter {:-write write-named})

I thought, I would put this example here for people, who are less experienced with Clojure protocols.
I hope it's the right approach :)

2 Answers

+1 vote
by

There's a note in https://clojure.atlassian.net/browse/DJSON-54 that touches on the functionality that you mention. As Alex said in his note, your proposal is a large change that would require some design work ahead of time. That said, I think your proposal is worth exploring and we could take up the conversation on that ticket.

by
I worked around my immediate need for this (turns out I was using `:value-fn` incorrectly, and it's adequate for my current needs), so I am unlikely to personally get involved in that discussion unless my needs change (which isn't impossible). I filed this request because Alex asked me to.
0 votes
by
...