from string to keyword?

2,480 views
Skip to first unread message

Avram

unread,
Mar 30, 2011, 3:04:12 PM3/30/11
to Clojure
hi,

I have 2 report files in JSON format like below:

# file 1: a.json
{ "abcdef" : { "value" : "10" }

# file 2: b.json
{ "abcdef" : { "value" : "20" }

I am using clojure.contrib.json to read each file, and I want a
function that takes in the 2 structures and a metric name (e.g.
abcdef). The function will then look up abcdef in each structure,
find the value of each, and compute the difference. I am running into
an issue, however, that the function needs to take in a string (e.g.
"abcdef") but convert this to a keyword (e.g. :abcdef ).

Thus I am looking for the opposite of as-str in
clojure.contrib.string, i.e. something that takes a string and creates
a keyword.
Or perhaps there is a better way?


This is what I have so far:

(use 'clojure.contrib.json)
(import 'java.io.FileReader)
(def report1 (clojure.contrib.json/read-json (FileReader.
"a.json" )) )
(def report2 (clojure.contrib.json/read-json (FileReader.
"b.json" )) )

;; Seek out the values from report1 and report2 for the metric desired
( e.g. :abcdef), and
;; compute the difference
;;-----------------------------------------------------------------------------
(defn compute-metric-diff [ json1 json2 :metric ]
(- (:value (json1 :metric )) (:value (json2 :metric))))

user=> (defn compute-metric-diff [ json1 json2 :metric ]
(- (:value (json1 :metric )) (:value (json2 :metric))))
java.lang.Exception: Unsupported binding form: :metric (NO_SOURCE_FILE:
58)

;; I want to be able to call it like so
(compute-metric-diff report1 report2 "abcdef" )

Any help appreciated.

Many thanks,
Avram

Alan

unread,
Mar 30, 2011, 3:11:20 PM3/30/11
to Clojure
(keyword "abcdef") => :abcdef

(defn metric-diff [metric & json-objs]
(apply - (map (comp :value (keyword metric)) json-objs)))

Probably does what you want.

Avram

unread,
Mar 30, 2011, 3:34:47 PM3/30/11
to Clojure
Many thanks!

Stuart Sierra

unread,
Mar 30, 2011, 5:24:32 PM3/30/11
to clo...@googlegroups.com
clojure.contrib.json (or the new clojure.data.json) has an option to *not* convert JSON Object keys into keywords.  I still think that should be the default, but I was out-shouted.

-Stuart Sierra
clojure.com

Avram

unread,
Mar 30, 2011, 6:02:14 PM3/30/11
to Clojure
One more thing…

If I try this, it looks okay
user=> (Integer/parseInt (:value (j1 (keyword "abcdef"))))
10

But within the function, I get cast exceptions.

user=> j1
{:abcdef {:value "10"}}
user=> j2
{:abcdef {:value "20"}}
user=> (defn metric-diff [metric & json-objs]
(apply - (map (comp (Integer/parseInt :value) (keyword metric))
json-objs)))
#'user/metric-diff
user=> (keyword "abcdef")
:abcdef
user=> (metric-diff (keyword "abcdef") j1 j2 )
java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to
java.lang.String (NO_SOURCE_FILE:0)

How can I coerce the JSON stringified numbers into integers ?

-Avram

Meikel Brandmeyer

unread,
Mar 30, 2011, 6:17:21 PM3/30/11
to clo...@googlegroups.com
Hi,

Am 31.03.2011 um 00:02 schrieb Avram:

> user=> (defn metric-diff [metric & json-objs]
> (apply - (map (comp (Integer/parseInt :value) (keyword metric))
> json-objs)))

(defn metric-diff
[metric & json-objs]

(apply - (map (comp #(Integer/parseInt %) :value (keyword metric)) json-objs))))

or

(defn metric-diff
[metric & json-objs]

(let [kmetric (keyword metric)]
(apply - (map #(-> % kmetric :value Integer/parseInt) json-objs))))

Sincerely
Meikel

Avram

unread,
Mar 30, 2011, 6:32:24 PM3/30/11
to Clojure
Perfect. Thanks again.
-A
Reply all
Reply to author
Forward
0 new messages