-
Notifications
You must be signed in to change notification settings - Fork 0
/
serde.clj
115 lines (83 loc) · 3.77 KB
/
serde.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
(ns kkiss.serde
(:require [clojure.string :as s]
[edamame.core :as edamame]
#_[hyperfiddle.rcf :refer [tests]]
[jsonista.core :as json]
[jsonista.tagged :as jt]))
(defmulti serializer (fn [kind & _] kind))
(defmulti deserializer (fn [kind & _] kind))
(defmulti serde (fn [kind & _] kind))
;; :string
(defmethod serializer :string [_ & _]
(fn [^String v] (some-> v .getBytes)))
(defmethod deserializer :string [_ & _]
(fn [^bytes bytes] (String. bytes java.nio.charset.StandardCharsets/UTF_8)))
;; edn
(defmethod serializer :edn [_ & _]
(let [ser (serializer :string)]
(fn [v] (some-> v pr-str ser))))
(defmethod deserializer :edn [_ & args]
(let [de (deserializer :string)
opts (first args)]
(fn [^bytes bytes]
(when bytes
(edamame/parse-string ((deserializer :string) bytes)
opts)))))
;; :keyword
(defmethod serializer :keyword [_ & _]
(let [ser (serializer :edn)]
(fn [^clojure.lang.Keyword v] (ser v))))
(defmethod deserializer :keyword [_ & _]
(let [de (deserializer :edn)]
(fn [^bytes bytes] (de bytes))))
;; json
(defmethod serializer :json [_ & args]
(if-let [mapper (first args)]
(fn [v] (some-> v (json/write-value-as-bytes mapper)))
(fn [v] (some-> v (json/write-value-as-bytes)))))
(defmethod deserializer :json [_ & args]
(if-let [mapper (first args)]
(fn [v] (some-> v (json/read-value mapper)))
(fn [v] (some-> v (json/read-value)))))
(defmethod serde :default [kind & args]
{:serializer (apply serializer kind args)
:deserializer (apply deserializer kind args)})
#_(tests
(tests
((deserializer :string) ((serializer :string) "Hello")) := "Hello")
(tests
((deserializer :keyword) ((serializer :keyword) :foobar)) := :foobar
((deserializer :keyword) ((serializer :keyword) :foo/bar)) := :foo/bar)
(tests
((deserializer :edn) ((serializer :edn) {:a :b})) := {:a :b}
((deserializer :edn) ((serializer :edn) {:foo/a 'b
"vals" ['qwe/rty
'(1 4.5)]})) := {:foo/a 'b
"vals" ['qwe/rty
'(1 4.5)]}
((deserializer :edn {:fn true}) ((serializer :string) "#(* % %1 %2)")) := '(fn* [%1 %2] (* %1 %1 %2)))
(tests
((deserializer :json) ((serializer :json) {"a" "b"})) := {"a" "b"}
(let [mapper (json/object-mapper
{:encode-key-fn true
:decode-key-fn true})]
((deserializer :json mapper) ((serializer :json mapper) {:a "b"}))) := {:a "b"}
(let [mapper (json/object-mapper
{:encode-key-fn true
:decode-key-fn true
:modules [(jt/module
{:handlers {clojure.lang.Keyword {:tag "!kw"
:encode jt/encode-keyword
:decode keyword}
clojure.lang.PersistentHashSet {:tag "!set"
:encode jt/encode-collection
:decode set}}})]})]
((deserializer :json mapper) ((serializer :json mapper)
{:system/status #{:status/good}}))) := {:system/status #{:status/good}})
(tests
(let [bytes (.getBytes ":foo/bar")
{:keys [serializer deserializer]} (serde :keyword)]
[(String. (serializer :foo/bar))
(deserializer bytes)]) := [":foo/bar" :foo/bar]
)
)