Cyr*_*rax 3 serialization record clojure
我试图将我的一个记录序列化为人类可读的格式.虽然使用Java序列化器进行序列化工作正常但我正在尝试使用print-dup.我面临的问题是,在编写记录时,可以很好地读取记录结果clojure.lang.LispReader $ ReaderException:java.lang.ClassNotFoundException:common.dummy.Doodh.我搞乱了命名空间或什么?请注意,这不是Java序列化的问题.以下代码以最简单的形式
(ns common.dummy)
(defrecord Doodh [id name])
(defn output [filename obj]
(def trr(map->Doodh {:id "moooh" :name "Cows"}))
(def my-string (binding [*print-dup* true] (pr-str trr)))
(spit filename my-string)
)
(defn pull [filename]
(def my-data (with-in-str (slurp filename) (read)))
(println my-data)
)
Run Code Online (Sandbox Code Playgroud)
文本文件内容:
#common.dummy.Doodh["moooh", "Cows"]
Run Code Online (Sandbox Code Playgroud)
不要在函数定义中使用def.当您使用def时,您在命名空间中创建一个var,并可能将其作为每个函数调用的副作用进行操作.使用let-blocks.
如果要将Clojure数据结构保存在文件中,请使用clojure.edn.它是安全的(例如,在您不知情的情况下,不会调用文件中定义的函数)但它允许启用自定义阅读器(请参阅下文).
使用defrecord定义的类型可以使用(Clojure-reader-)可读方式打印pr-str(感谢@A.Web注意到).在你的例子中,我不明白你为什么不首先坚持使用哈希映射,但是如果你真的需要一个defrecord,你可以在将它写入文件之前将其转换为可读字符串.
(defrecord Doodh [id name])
(defn output [filename obj]
(spit filename (pr-str obj))
(defn pull [filename]
(with-in-str (slurp filename)
(read)))
Run Code Online (Sandbox Code Playgroud)
read会使您的代码容易受到slurped文件中的函数调用(如#=(java.lang.System/exit 0)).使用带EDN的自定义阅读器
我们通过实现java.lang.Object接口的toString方法来扩展我们的类型Doodh:
(defrecord Doodh [id name]
Object
(toString [this] (str "#Doodh" (into {} this))))
Run Code Online (Sandbox Code Playgroud)因为spit使用str,我们现在可以省略输出函数并简单地从例如REPL调用spit:
(spit "Doodh.edn" (map->Doodh {:id "134" :name "Berta"}))
Run Code Online (Sandbox Code Playgroud)
Doodh.edn:#Doodh {:id 134,:name"Berta"}
现在为了确保读回Doodh,我们clojure.edn/read-string使用自定义读取器功能调用:
(defn pull [filename]
(->> (slurp filename)
(clojure.edn/read-string {:readers {'Doodh map->Doodh}})))
Run Code Online (Sandbox Code Playgroud)如果您使用新拉回读"Doodh.edn",您应该收到有效的Doodh.在REPL:
(pull "Doodh.edn")
=> #user.Doodh{:id 134, :name "Berta"}
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
710 次 |
| 最近记录: |