gpt4 book ai didi

serialization - Clojure defrecord 序列化 ClassNotFoundException

转载 作者:行者123 更新时间:2023-12-01 10:52:03 27 4
gpt4 key购买 nike

我试图将我的一个记录序列化为人类可读的格式。虽然使用 Java serialiser 进行序列化工作正常,但我正在尝试使用 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 block 。

  • 如果您想将 Clojure 数据结构保存在文件中,请使用 clojure.edn。它是安全的(例如,在您不知情的情况下,不会调用文件中定义的任何函数)但它允许启用自定义阅读器(请参见下文)。

  • 使用 defrecord 定义的类型可以使用 pr-str 以 (Clojure-reader-) 可读的方式打印(感谢 @A.Webb 注意到这一点)。在你的例子中,我不明白你为什么不首先坚持使用 HashMap ,但如果你真的需要一个 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 声明移动到另一个 namespace 时,您保存的文件将变得与您的代码不兼容。
      • 使用 edn-reader 可以避免这三个缺点。

将自定义阅读器与 EDN 结合使用

  1. 我们通过实现 java.lang.Object 接口(interface)的 toString 方法来扩展我们的类型 Doodh:

    (defrecord Doodh [id name]
    Object
    (toString [this] (str "#Doodh" (into {} this))))
  2. 因为 spit 使用 str,我们现在可以省略输出函数并简单地从 e 调用 spit。 G。回复:

    (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. 如果您使用新的 pull 回读“Doodh.edn”,您应该会收到一个有效的 Doodh。在 REPL:

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

关于serialization - Clojure defrecord 序列化 ClassNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17991565/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com