EDN in Clojure should be paradise. But all too often it isn't.
Examples of frustrating behavior:
pr-stroutputs invalid EDN when there are regexen in your data.- There is no
clojure.edn/writenorclojure.edn/write-string. - Defining new data readers is cumbersome and disconnected from defining the counterpart tagged encoding.
clojure.edn/read&cloure.edn/read-stringthrow exceptions on unknown tags.
Paradise is different. In contrast, it...
- Defines all of the following to do what you'd expect:
paradise.edn/readparadise.edn/read-stringparadise.edn/writeparadise.edn/write-string
- Allows easily defining custom data types that will round-trip through these
fns (without modifying how they normally print at the REPL via
print-method). - Round-trips regexen like a champ (again assuming you're using its read & write fns).
- Just ignores unknown tags, placing the raw value in the returned data structure.
In your project dependencies, add:
[paradise "0.1.0"]
Then in your code:
(ns my.app
(:require
[paradise.edn :as edn]))
(def some-edn (edn/write-string {:regex #"itworks"}))
(def original-data (edn/read-string some-edn))To allow custom data types to round-trip through EDN:
(ns my.app
(:require
[paradise.edn :as edn]))
(defrecord MyRecord [foo bar])
(defmethod edn-encode MyRecord [r] [:my/record (into {} r)])
(defmethod edn-read :my/record [[tag m]] (map->MyRecord m))edn-encode is a multi-method that dispatches on class. Its purpose is to
prepare custom data types for EDN encoding by defining a tag and an EDN
representation to follow the tag. To define new methods, just specify a
defmethod form with the class you want to encode as the dispatch value, take
one arg (an instance of that class), and return a vector whose first element is
a namespaced keyword that will become the tag in the resulting EDN and whose
second element is the EDN-encodable value you want to follow the tag.
edn-read is a multi-method that dispatches on first. Its purpose is to
associate reader fns with EDN tags so that they can be turned back into their
original values. To define new methods, just specify a defmethod form with
the namespaced keyword representing the EDN tag as the dispatch value, take one
arg (a 2-element vector of [tag value]; feel encouraged to destructure that),
and return the EDN representation converted back into an instance of the
original class.
Copyright © 2017 Democracy Works, Inc.
Distributed under the Mozilla Public License either version 2.0 or (at your option) any later version.