Clojure сериализация структуры данных - PullRequest
17 голосов
/ 21 июля 2010

У меня сложная структура данных Clojure, которую я хотел бы сериализовать - в основном, все текущее состояние игры для сетевой игры, которую я разрабатываю, чтобы я мог реализовать сохранение файлов игры.

Мои требования:

  • Некоторая форма читаемого человеком текстового формата (вероятно, я бы предпочел s-выражения, JSON и XML в этом порядке, но открыт для других)
  • Поддержка всех обычных структур данных Clojure, ключевые слова и примитивы
  • Возможность предоставлять настраиваемые функции сериализации / десериализации для пользовательских классов Java, defrecords и т. д. (это важно, потому что мне нужно сделать что-то вроде readResolve Java в некоторых случаях)
  • Хорошопроизводительность - это хорошо, чтобы иметь

Любые хорошие рекомендации?

Ответы [ 4 ]

11 голосов
/ 21 июля 2010

Если вы хотите сериализовать вещи в 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?), хотя эквивалентными в терминах структурных (=) векторами .

Чтобы использовать это в тех случаях, когда не предусмотрена реализация по умолчанию, реализуйте мультиметод clojure.core/print-dup.

Кроме того, в Clojure 1.2 есть много вещей, которые 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

Обратите внимание, что вам следует избегать сериализации созданных во время выполнения fn s - они являются экземплярами одноразовых классов со странными именами, и вы не сможете десериализовать их после перезапуска JVM в любом случае. С компиляцией AOT fn s получают свои собственные фиксированные имена классов.

Обновление: Как уже упоминалось в комментарии к вопросу, Serializable лучше всего подходит для кратковременного хранения / передачи данных, тогда как print-dup должно быть более устойчивым в качестве долговременного хранилища. решение (работает во многих версиях приложения, Clojure и т. д.). Причина в том, что print-dup никак не зависит от структуры сериализуемых классов (поэтому вектор print-dup 'd сегодня будет по-прежнему читаемым, когда реализация вектора переключится с Java на Clojure deftype).

7 голосов
/ 07 октября 2012

edn-формат теперь выпущен в качестве стандарта для передачи данных с использованием структур данных Clojure.

Он очень хорошо подходит для сериализации структур / значений данных Clojure - и поддерживаетсяна нескольких языках, поэтому также может использоваться в качестве формата обмена данными.

5 голосов
/ 21 июля 2010

Если все является структурой данных Clojure, то она уже сериализована (b / c кода <-> data).Просто сбросьте структуры данных на диск.Для восстановления загрузите их обратно и (eval).

3 голосов
/ 21 июля 2010

для JSON вы можете использовать стандарт clojure-contrib.json .Хотя, насколько я помню, все объекты Clojure должны быть сериализуемыми ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...