Clojure数据结构序列化

时间:2010-07-21 16:14:05

标签: java serialization clojure

我有一个复杂的Clojure数据结构,我想序列化 - 基本上是我正在开发的在线游戏的整个当前游戏状态,以便我可以实现保存游戏文件。

我的要求是:

  • 某种形式的人类可读的文本格式(我可能更喜欢s-expressions,JSON和XML,但是对其他人开放)
  • 支持所有常用的Clojure数据结构,关键字和基元
  • 能够为自定义java类,defrecords等提供自定义序列化/反序列化功能(这很重要,因为我需要在几种情况下执行类似Java的readResolve)
  • 良好的表现是一件好事

有什么好建议吗?

4 个答案:

答案 0 :(得分:11)

如果您想将事物序列化为S表达式,可以使用print-dup

(binding [*print-dup* true] (println [1 2 3]))
; prints [1 2 3]

(defrecord Foo [x])
; => user.Foo
(binding [*print-dup* true] (println (Foo. :foo)))
; prints #=(user.Foo/create {:x :foo})

请注意,打印一个结构,其中包含对单个向量的十个引用,然后将其读回来为您提供一个具有十个单独(不是identical?)的数据结构,尽管在结构方面是等效的({{1 }})vector。

要在没有提供默认实现的情况下使用它,请实现多方法=

此外,Clojure 1.2中的很多内容都是clojure.core/print-dup

java.io.Serializable

请注意,您应该避免序列化运行时创建的(every? (partial instance? java.io.Serializable) [{1 2} #{"asdf"} :foo 'foo (fn [] :foo)]) ; => true (defrecord Foo []) (instance? java.io.Serializable (Foo.)) ; => true - 它们是具有奇怪名称的一次性类的实例,并且无论如何重新启动JVM后都无法对它们进行反序列化。通过AOT编译,fn可以获得自己的固定类名。

更新:正如对该问题的评论中所述,fn最适合短期存储/传输数据,而Serializable应该更加强大一个长期存储解决方案(适用于许多版本的应用程序,Clojure等)。原因是print-dup在任何方面都不依赖于被序列化的类的结构(因此当向量实现从Java切换到Clojure时,今天的向量print-dup'仍然可读。 {1}})。

答案 1 :(得分:7)

edn-format现已作为使用Clojure数据结构进行数据传输的标准发布。

它非常适合序列化Clojure数据结构/值 - 并且支持多种语言,因此也可以用作数据交换格式。

答案 2 :(得分:5)

如果一切都是Clojure数据结构,那么它已经被序列化了(b / c代码< - >数据)。只需将数据结构转储到磁盘上。要恢复,请将它们加载回来(eval)。

答案 3 :(得分:3)

对于JSON,您可以使用标准clojure-contrib.json。虽然,我记得,所有Clojure对象都应该是可序列化的......