Clojure: Writing JSON to a file/reading JSON from a file
A few weeks ago I described how I’d scraped football matches using Clojure’s Enlive, and the next step after translating the HTML representation into a Clojure map was to save it as a JSON document.
I decided to follow a two step process to achieve this:
-
Convert hash to JSON string
-
Write JSON string to file
I imagine there’s probably a way to convert the hash to a stream and pipe that into a file but my JSON document isn’t very large so I think this way is ok for now.
https://github.com/clojure/data.json seems to be the way to go to convert a Hash to a JSON string and I had the following code:
> (require '[clojure.data.json :as json])
nil
> (json/write-str { :key1 "val1" :key2 "val2" })
"{\"key2\":\"val2\",\"key1\":\"val1\"}"
The next step was to write that into a file and this StackOverflow post describes a couple of ways that we can do this:
> (use 'clojure.java.io)
> (with-open [wrtr (writer "/tmp/test.json")]
(.write wrtr (json/write-str {:key1 "val1" :key2 "val2"})))
or
> (spit "/tmp/test.json" (json/write-str {:key1 "val1" :key2 "val2"}))
Now I wanted to read the file back into a hash and I started with the following:
> (json/read-str (slurp "/tmp/test.json"))
{"key2" "val2", "key1" "val1"}
That’s not bad but I wanted the keys to be what I know as symbols (e.g. ':key1') from Ruby land. I re-learnt that this is called a keyword in Clojure.
Since I’m not very good at reading the documentation I wrote a function to convert all the keys in a map from strings to keywords:
> (defn string-keys-to-symbols [map]
(reduce #(assoc %1 (-> (key %2) keyword) (val %2)) {} map))
> (string-keys-to-symbols (json/read-str (slurp "/tmp/test.json")))
{:key1 "val1", :key2 "val2"}
What I should have done is pass the http://clojuredocs.org/clojure_core/clojure.core/keyword function as an argument to read-str instead:
> (json/read-str (slurp "/tmp/test.json") :key-fn keyword)
{:key2 "val2", :key1 "val1"}
Simple!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.