簡體   English   中英

Clojure defrecord序列化ClassNotFoundException

[英]Clojure defrecord serialization ClassNotFoundException

我試圖將我的一個記錄序列化為人類可讀的格式。 雖然使用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)
   )

文本文件內容:

#common.dummy.Doodh["moooh", "Cows"]
  • 不要在函數定義中使用def。 當您使用def時,您在命名空間中創建一個var,並可能將其作為每個函數調用的副作用進行操作。 使用let-blocks。

  • 如果要將Clojure數據結構保存在文件中,請使用clojure.edn 它是安全的(例如,在您不知情的情況下,不會調用文件中定義的函數)但它允許啟用自定義閱讀器(請參閱下文)。

  • 用defrecord定義的類型可以使用pr-str以(Clojure-reader-)可讀方式打印(感謝@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))) 
    • 這種做法有幾個缺點。
      • 使用read會使您的代碼容易受到slurped文件中的函數調用的攻擊(例如#=(java.lang.System/exit 0) )。
      • 當filename的文件為空時,將拋出異常。
      • 最后,當您將defrecord聲明移動到另一個命名空間時,您保存的文件將與您的代碼不兼容。
      • 使用edn-reader可以避免所有這三個缺點。

使用帶EDN的自定義閱讀器

  1. 我們通過實現java.lang.Object接口的toString方法來擴展我們的類型Doodh:

     (defrecord Doodh [id name] Object (toString [this] (str "#Doodh" (into {} this)))) 
  2. 因為spit使用str,我們現在可以省略輸出函數並簡單地從例如REPL調用spit:

     (spit "Doodh.edn" (map->Doodh {:id "134" :name "Berta"})) 

    Doodh.edn:#Doodh {:id 134,:name“Berta”}

  3. 現在為了確保讀回Doodh,我們使用自定義讀取器函數調用clojure.edn/read-string

     (defn pull [filename] (->> (slurp filename) (clojure.edn/read-string {:readers {'Doodh map->Doodh}}))) 
  4. 如果您使用新拉回讀“Doodh.edn”,您應該收到有效的Doodh。 在REPL:

     (pull "Doodh.edn") => #user.Doodh{:id 134, :name "Berta"} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM