Proper EDN serialization
This commit is contained in:
parent
ecc4fa4b7e
commit
ab8a0c5860
|
@ -1,21 +1,23 @@
|
||||||
(ns hottub.serialize
|
(ns hottub.serialize
|
||||||
(:require [clojure.edn :as edn]))
|
(:require [clojure.edn :as edn]
|
||||||
|
[net.information-superhighway.edn :as ednw]))
|
||||||
|
|
||||||
(defmethod print-dup clojure.lang.PersistentQueue [o w]
|
(defn is-queue [q] (isa? (type q) clojure.lang.PersistentQueue))
|
||||||
(.append w "#hottub/queue ")
|
(defn serialize-queue [q] (into [] q))
|
||||||
(print-dup (into [] o) w))
|
(defn deserialize-queue [l] (into clojure.lang.PersistentQueue/EMPTY l))
|
||||||
|
|
||||||
(defn deserialize-queue [l]
|
(def writer-opts
|
||||||
(into clojure.lang.PersistentQueue/EMPTY l))
|
{:tagged-serializers ['hottub.queue is-queue serialize-queue]})
|
||||||
|
|
||||||
|
(def reader-opts
|
||||||
|
{:readers {'hottub.queue deserialize-queue}})
|
||||||
|
|
||||||
(defn write
|
(defn write
|
||||||
([o] (with-open [w (java.io.StringWriter.)]
|
([o] (ednw/stringify o writer-opts))
|
||||||
(write o w)
|
([o w] (ednw/write o w writer-opts)))
|
||||||
(.toString w)))
|
|
||||||
([o w] (print-dup o w)))
|
|
||||||
|
|
||||||
(defmulti read class)
|
(defmulti read class)
|
||||||
(defmethod read String [s] (read (java.io.StringReader. s)))
|
(defmethod read String [s] (read (java.io.StringReader. s)))
|
||||||
(defmethod read java.io.Reader [r]
|
(defmethod read java.io.Reader [r]
|
||||||
(with-open [pbr (java.io.PushbackReader. r)]
|
(with-open [pbr (java.io.PushbackReader. r)]
|
||||||
(edn/read {:readers {'hottub/queue deserialize-queue}} pbr)))
|
(edn/read reader-opts pbr)))
|
||||||
|
|
80
src/net/information_superhighway/edn.clj
Normal file
80
src/net/information_superhighway/edn.clj
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
(ns net.information-superhighway.edn)
|
||||||
|
|
||||||
|
(defn serialize-pr [val opts w]
|
||||||
|
"Serializes an arbitrary value to EDN using clojure.core/pr."
|
||||||
|
(binding [*out* w] (pr val)))
|
||||||
|
|
||||||
|
(defn serialize-number [num opts w]
|
||||||
|
"Serialize a number to EDN. Converts ratios to doubles."
|
||||||
|
(let [out (if (integer? num) num (double num))]
|
||||||
|
(.append w (str out))))
|
||||||
|
|
||||||
|
(declare write)
|
||||||
|
|
||||||
|
(defn- serialize-children [open close vals opts w]
|
||||||
|
(.append w open)
|
||||||
|
(loop [vals vals isfirst true]
|
||||||
|
(if (seq vals)
|
||||||
|
(do
|
||||||
|
(if-not isfirst (.append w " "))
|
||||||
|
(write (first vals) opts w)
|
||||||
|
(recur (next vals) false))))
|
||||||
|
(.append w close))
|
||||||
|
|
||||||
|
(defn serialize-list [l opts w]
|
||||||
|
(serialize-children "(" ")" l opts w))
|
||||||
|
|
||||||
|
(defn serialize-set [s opts w]
|
||||||
|
(serialize-children "#{" "}" s opts w))
|
||||||
|
|
||||||
|
(defn serialize-vector [v opts w]
|
||||||
|
(serialize-children "[" "]" v opts w))
|
||||||
|
|
||||||
|
(defn serialize-map [m opts w]
|
||||||
|
(serialize-children "{" "}" (mapcat identity m) opts w))
|
||||||
|
|
||||||
|
(def default-serializers
|
||||||
|
[keyword? serialize-pr
|
||||||
|
string? serialize-pr
|
||||||
|
number? serialize-number
|
||||||
|
#(or (= % true) (= % false)) serialize-pr
|
||||||
|
map? serialize-map
|
||||||
|
vector? serialize-vector
|
||||||
|
nil? serialize-pr
|
||||||
|
symbol? serialize-pr
|
||||||
|
list? serialize-list
|
||||||
|
set? serialize-set
|
||||||
|
char? serialize-pr])
|
||||||
|
|
||||||
|
(defn write-default [val opts w]
|
||||||
|
"Serialize to EDN using only the baseline serializers (no tagged values)"
|
||||||
|
(loop [serializers (partition 2 default-serializers)]
|
||||||
|
(if (seq serializers)
|
||||||
|
(let [[fntest fnserialize] (first serializers)]
|
||||||
|
(if (fntest val)
|
||||||
|
(fnserialize val opts w)
|
||||||
|
(recur (next serializers))))
|
||||||
|
(throw (Exception. (str "Could not serialize " val))))))
|
||||||
|
|
||||||
|
(defn serialize-tagged [tag value opts w]
|
||||||
|
(.append w (str "#" tag " "))
|
||||||
|
(write-default value opts w))
|
||||||
|
|
||||||
|
(def default-opts nil)
|
||||||
|
(defn write
|
||||||
|
([val w] (write val default-opts w))
|
||||||
|
([val opts w]
|
||||||
|
(loop [tagged-serializers (partition 3 (:tagged-serializers opts))]
|
||||||
|
(if (seq tagged-serializers)
|
||||||
|
(let [[tag fntest fnserialize] (first tagged-serializers)]
|
||||||
|
(if (fntest val)
|
||||||
|
(serialize-tagged tag (fnserialize val) opts w)
|
||||||
|
(recur (next tagged-serializers))))
|
||||||
|
(write-default val opts w)))))
|
||||||
|
|
||||||
|
(defn stringify
|
||||||
|
([val] (stringify val default-opts))
|
||||||
|
([val opts]
|
||||||
|
(with-open [w (java.io.StringWriter.)]
|
||||||
|
(write val opts w)
|
||||||
|
(.toString w))))
|
Loading…
Reference in a new issue