自定义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}]