Подтвердить что ты не робот

Clojure сериализация структуры данных

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

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

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

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

4b9b3361

Ответ 1

Если вы хотите сериализовать вещи в 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 - это экземпляры одноразовых классов со странными именами, и вы не сможете их десериализовать после перезапуска вашей JVM. С помощью компиляции AOT fn получают собственные фиксированные имена классов.

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

Ответ 2

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

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

Ответ 3

Если все это структура данных Clojure, то она уже сериализована (b/c из кода ↔ data). Просто удалите структуры данных на диск. Чтобы восстановить, загрузите их и (eval).

Ответ 4

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