Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the "Correct" way to write an EDN file in Clojure as of August 2013?

Tags:

clojure

edn

I would like to write out an EDN data file from Clojure as tagged literals. Although the clojure.edn API contains read and read-string, there are no writers. I'm familiar with the issue reported here. Based on that, it's my understanding that the pr and pr-str functions are what are meant to be used today.

I wanted to check with the StackOverflow community to see if something like the following would be considered the "correct" way to write out an EDN file:

(spit "friends.edn" (apply str 
  (interpose "\n\n"
             [(pr-str (symbol "#address-book/person") {:name "Janet Wood"})
              (pr-str (symbol "#address-book/person") {:name "Jack Tripper"})
              (pr-str (symbol "#address-book/person") {:name "Chrissy Snow"})])))

If you are using EDN in production, how do you write out an EDN file? Similar to the above? Are there any issues I need to look out for?

Update

The Clojure Cookbook entry, "Emitting Records as EDN Values" contains a more thorough explanation of this issue and ways to handle it that result in valid EDN tags.

like image 311
mokeefe Avatar asked Aug 27 '13 21:08

mokeefe


People also ask

What is EDN in Clojure?

Extensible Data Notation or EDN is the Clojure equivalent of JSON: using the language's literal syntax for data serialisation. Some people recommend EDN for serialisation in full-stack Clojure projects.

What is an EDN file?

Extensible Data Notation (EDN) is a format for serializing data. EDN is a subset of the syntax used by Clojure. Reading data defined by EDN is safer than that defined by the full Clojure syntax, especially from untrusted sources. EDN is restricted to data, no code. It is similar in intent to JSON.


1 Answers

you should not need to generate the tags manually. If you use any of the clojure type definition mechanisms they will be created by the printer. defrecord is particularly convenient for this.

(ns address-book)
(defrecord person [name])

(def people [(person. "Janet Wood")
             (person. "Jack Tripper")
             (person. "Chrissy Snow")])

address-book> (pr-str people)
"[#address_book.person{:name \"Janet Wood\"} 
  #address_book.person{:name \"Jack Tripper\"} 
  #address_book.person{:name \"Chrissy Snow\"}]"

if you want them formatted more nicely you can combine with-out-str and clojure.pprint/pprint. Using Clojure types to create the tags also gives you reading of those tags for free.

address-book> (read-string (pr-str people))
[#address_book.person{:name "Janet Wood"} 
 #address_book.person{:name "Jack Tripper"} 
 #address_book.person{:name "Chrissy Snow"}]

address-book> (def read-people (read-string (pr-str people)))
#'address-book/read-people

address-book> (type (first read-people))
address_book.person

The only downside I see is that you lose some control over the way the tags look if you have -'s in your namespace because java classes can't contain these so they get converted to underscores.

like image 180
Arthur Ulfeldt Avatar answered Sep 24 '22 06:09

Arthur Ulfeldt