自定义EDN的reader function
需求
有时需要在EDN的数据结构中, 写一些自定义的类型.
如果使用 (:some-type x) 或者 [:some-tye x], 不好处理.
理想的情况是我们读取到数据的时候, 直接将其转换成对应的类型.
而不是用传统的方式, 先将数据处理成普通的数据结构, 再逐步处理特定的部分.
解决方案
使用自定义的 reader function. 假设我们接受的数据结构(EDN字符串)如下:
[{:name "Dog.LooksGood"
:age 18}
{:name "Foo.Bar"
:age 16}]
我们希望得到
[{:name {:first "Dog"
:last "LooksGood"}
:age 18}
{:name {:first "Foo"
:last "Bar"}
:age 16}]
首先, 我们自定义一个标签 #name 来标识一种特殊的数据处理方式.
接受的数据应该应该为
[{:name #name "Dog.LooksGood"
:age 18}
{:name #name "Foo.Bar"
:age 16}]
使用 clojure.edn/read-string 的时候, 传入自定义reader function.
(require '[clojure.edn :as edn])
;; EDN数据
(def edn-string
"[{:name #name \"Dog.LooksGood\"
:age 18}
{:name #name \"Foo.Bar\"
:age 16}]")
;; 自定义reader
(defn parse-name [name]
(let [[f l] (clojure.string/split name #"\.")]
{:first f
:last l}))
(edn/read-string
{:readers {'name parse-name}}
edn-string)
;; =>[{:name {:first "Dog", :last "LooksGood"}, :age 18} {:name {:first "Foo", :last "Bar"}, :age 16}]