Serialization Clojure defrecord序列化类NotFoundException
我试图将我的一条记录序列化为人类可读的格式。虽然使用Java serialiser进行序列化工作正常,但我正在尝试使用打印dup。我面临的问题是,在编写记录时,读取clojure.lang.LispReader$ReaderException:java.lang.ClassNotFoundException:common.dummy.Doodh中的记录结果会很顺利。我是不是把名字空间搞砸了? 请注意,这不是Java序列化的问题。 下面以最简单的形式编写代码Serialization Clojure defrecord序列化类NotFoundException,serialization,clojure,record,Serialization,Clojure,Record,我试图将我的一条记录序列化为人类可读的格式。虽然使用Java serialiser进行序列化工作正常,但我正在尝试使用打印dup。我面临的问题是,在编写记录时,读取clojure.lang.LispReader$ReaderException:java.lang.ClassNotFoundException:common.dummy.Doodh中的记录结果会很顺利。我是不是把名字空间搞砸了? 请注意,这不是Java序列化的问题。 下面以最简单的形式编写代码 (ns common.dummy)
(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)
)
文本文件内容:
#common.dummy.Doodh["moooh", "Cows"]
- 不要在函数定义中使用def。使用def时,在名称空间中创建一个var,并可能将其作为每个函数调用的副作用进行操作。使用let块
- 如果要在文件中保存Clojure数据结构,请使用
。它是安全的(例如,在您不知道的情况下,不会调用文件中定义的函数),但它允许启用自定义读卡器(请参阅下文)Clojure.edn
- 使用defrecord定义的类型可以使用
以(Clojure reader-)可读的方式打印(感谢@A.Webb注意到这一点)。在您的示例中,我不明白您为什么不首先坚持使用散列映射,但是如果您确实需要这里的defrecord,您可以在将其写入文件之前将其转换为可读字符串pr str
(defrecord Doodh [id name]) (defn output [filename obj] (spit filename (pr-str obj)) (defn pull [filename] (with-in-str (slurp filename) (read)))
- 这种做法有几个缺点。
- 使用
会使代码容易受到slurped文件中函数调用的攻击(如read
)#=(java.lang.System/exit 0)
- 当文件名处的文件为空时,将引发异常
- 最后,当您将defrecord声明移动到另一个命名空间时,保存的文件将与代码不兼容李>
- 使用edn阅读器可以避免所有三个缺点
- 使用
- 这种做法有几个缺点。
(defrecord Doodh [id name]
Object
(toString [this] (str "#Doodh" (into {} this))))
(spit "Doodh.edn" (map->Doodh {:id "134" :name "Berta"}))
(pull "Doodh.edn")
=> #user.Doodh{:id 134, :name "Berta"}
Doodh.edn:
#Doodh{ID134,:name“Berta”}
clojure.edn/read string
:
(defn pull [filename]
(->> (slurp filename)
(clojure.edn/read-string {:readers {'Doodh map->Doodh}})))
(spit "Doodh.edn" (map->Doodh {:id "134" :name "Berta"}))
(pull "Doodh.edn")
=> #user.Doodh{:id 134, :name "Berta"}
顺便问一下,什么是Doodh?不能重现错误。报告`*clojure版本*和生成异常的测试。Doodh=Milk。因此moohs和cows.@A.Webb-Webb-Clojure版本{:major 1,:minor 5,:incremental 1,:qualifier nil}。不太确定是否相关,但我使用的是ring、lacij、tikkba。正如我在前面提到的,当我在做一个纯粹的基于Java的序列化时,这种方法可以很好地工作。请注意名称空间。我报告的错误不是来自repl,您的答案所指的是哪个`*clojure版本*?我想你的第三点可能已经过时了。你是在暗示它会自动为#user.Doodh选择一个读卡器fn吗?哦,你指的是
edn
读卡器?否,但将调用构造函数。短语“不能以(Clojure reader-)可读的方式打印”是一种混淆。换句话说,(带有in-str(pr-str(common.dummy.Doodh.foo“bar”))(Clojure.core/read))
是Clojure阅读器,工作正常。但是,是的,(带in-str(pr-str(common.dummy.Doodh.foo”“bar))(clojure.edn/read))
会抱怨edn没有读卡器功能。非常感谢您的澄清。我不知道Clojure阅读器能够读回打印的记录。我会更新我的答案。