How to keep keywords in arrays when converting to json using js->clj?

573 Views Asked by At

My actual behavior is

(js->clj (clj->js [:a :b :c]) :keywordize-keys true)
=> ["a" "b" "c"]

Desired behavior

[:a :b :c]
1

There are 1 best solutions below

5
On

I don't use ClojureScript, but it should be noted that :keywordize-keys isn't doing anything likely because vectors are keyed by index. The elements of the vector are the values, not the indices.

You could do something like

(->> [:a :b :c]
     (clj->js)
     (js->clj)
     (mapv keyword))

; Should print [:a :b :c]

Of course, this gets a little more complicated if the structure is nested, but it's the same general idea.


Since JSON doesn't recognize the concept of a "keyword" though, there's no simple way of converting between the two formats and maintaining what is a String and what is a Keyword. If you really need to differentiate, you could use Clojure's EDN format instead of JSON. This would only work though if you aren't doing excessive JavaScript interop. Any data exchanged with a plain JS library will involve the conflation of Keywords and Strings unless the library understands EDN formatting, or you do something unfortunate like attaching some kind of metadata to the object indicating what is a keyword and what isn't.

You could also just do away with the idea of keywords altogether and use Strings for everything internally. That would suck, but at least it would make the interop easier.