tl;dr
How can I derive a keyword from a number in ClojureScript:
(keyword 22)
;;=> :22 but in fact returns nil.
Background
In my ClojureScript/Hoplon application I make HTTP requests via cljs-http. Parts of the response I receive look like this:
{:companies
{:22 {:description ... } ; A company.
:64 {:description ... }
... }
{:offers
[{:description ... } ; An offer.
{:description ... }
... ]
Each offer within the vector behind :offers
has a :companyId
which represents a key in :companies
. As soon as I receive the response, I reset!
a cell (similar to an atom) query
.
Now, I'd like to iterate over each offer and call a function offer-tpl
that creates the corresponding HTML. In order to do so, offer-tpl
needs the offer itself as well as the related company:
(for [offer (:offers @query)]
(offer-tpl offer (get-in @query [:companies (keyword (:companyId offer))]))))))
Despite the fact that this surely can be done more elegant (suggestions very appreciated), the get-in
doesn't work. (:companyId offer)
returns a number (e.g. 22
) but (keyword (:companyId offer))
returns nil
. Calling (keyword (str (:companyId offer)))
does the trick, but aren't there any other ways to do this?
(keyword "22")
or(keyword (str 22))
returns:22
The reason you are getting
:22
is likely because of thekeywordize-keys
option of a JSON translation. For example:cljs-http defaults to keywordize-keys for jsonp: https://github.com/r0man/cljs-http/blob/1fb899d3f9c5728521786432b5f6c36d1d7a1452/src/cljs_http/core.cljs#L115 But you can (and should) in this case pass in a flag to disable keywordization.
Not all keys in JSON are appropriate for Clojure keywordization. For example spaces in a JSON key are valid, but not in Clojure.
Please be aware that numeric keywords are probably incorrect. https://clojuredocs.org/clojure.core/keyword#example-542692cec026201cdc326d70 It seems like that caveat has been removed from the current Clojure website, so perhaps that means something but I'm not sure what.
http://clojure.org/reference/reader Currently states that
and that
This definition of a keyword excludes
:22
and:with spaces
The keyword function returns a result for invalid input, but this is not an endorsement, it is simply because checking for incorrect input would be a performance overhead in a core part of Clojure.
In short, not all JSON keys translate to keywords, so you should avoid
keywordize-keys
unless you know the keyspace and/or doing so provides some conveniences.