Как мне сделать автоматическую сериализацию данных объектов данных? - PullRequest
15 голосов
/ 22 апреля 2010

Одним из огромных преимуществ в языках, которые имеют своего рода отражение / интроспекцию, является то, что объекты могут автоматически создаваться из различных источников.

Например, в Java я могу использовать одни и те же объекты для сохранения в БД (с Hibernate), сериализации в XML (с JAXB) и сериализации в JSON (json-lib). Вы можете сделать то же самое в Ruby и Python, обычно следуя некоторым простым правилам для свойств или аннотаций для Java.

Таким образом, мне не нужны лоты "Объекты передачи домена". Я могу сосредоточиться на области, в которой я работаю.

Кажется, что в очень строгих FP, таких как Haskell и Ocaml, это невозможно. Особенно Haskell. Единственное, что я видел, - это какая-то предварительная обработка или метапрограммирование (ocaml). Просто принято, что вам нужно делать все преобразования снизу вверх?

Другими словами, вам нужно проделать много скучной работы, чтобы превратить тип данных в haskell в объект строки JSON / XML / DB и снова в объект данных.

Ответы [ 5 ]

28 голосов
/ 22 апреля 2010

Я не могу говорить с OCaml, но я бы сказал, что основная трудность в Haskell заключается в том, что для десериализации необходимо заранее знать тип - универсального способа механической десериализации из формата не существует,выясните, каково полученное значение, и перейдите оттуда, как это возможно в языках с ненадежными или динамическими системами типов.

Если не учитывать проблему типов, существуют различные подходы к сериализации данных в Haskell:

  • Классы встроенных типов Read / Show (де) сериализуют алгебраические типы данных и большинство встроенных типов как строки.Как правило, экземпляры с хорошим поведением должны быть такими, чтобы read . show эквивалентно id и чтобы результат show можно было проанализировать как исходный код Haskell, создающий сериализованное значение.

  • Различные пакеты сериализации можно найти на Hackage;обычно для этого требуется, чтобы сериализуемый тип был экземпляром некоторого класса типов, а пакет предоставляет экземпляры для большинства встроенных типов.Иногда они просто требуют автоматически выводимого экземпляра класса отражающего метапрограммирования Data с изменяющим тип типом (очаровательное полностью определенное имя, для которого Data.Data.Data), или предоставляют код Template Haskell для автоматической генерации экземпляров.

  • Для действительно необычных форматов сериализации - или для создания собственного пакета, подобного ранее упомянутым - можно достичь самого большого доступного молотка, своего рода «старшего брата», до Read и Show: разбор и симпатичная печать.Для обоих доступно множество пакетов, и, хотя поначалу это может показаться пугающим, в Haskell парсинг и симпатичная печать на самом деле удивительно безболезненны.

Взгляд на Hackage указывает на то, что пакеты сериализации ужесуществуют для различных форматов, включая двоичные данные, JSON, YAML и XML, хотя я не использовал ни один из них, поэтому я не могу лично подтвердить, насколько хорошо они работают.Вот неполный список, с которого можно начать:

  • двоичный : ориентированная на производительность сериализация до ленивых ByteString с
  • зерновой : Аналогично двоичному, но немного другому интерфейсу и использует строгий ByteString s
  • genericserialize : сериализация с помощью встроенного метапрограммирования, формат вывода расширяемый, включает вывод R5RS sexp.
  • json : упрощенная сериализация данных JSON
  • RJson : сериализация в JSON посредством встроенного метапрограммирования
  • hexpat-pickle : комбинаторы для сериализации в XML с использованием пакета "hexpat"
  • регулярный-xmlpickler : сериализация в XML рекурсивных структур данных с использованием "обычного" пакета

Единственная другая проблема состоит в том, что неизбежно не все типы будут сериализуемыми - если ничего другого, я подозреваю, вам будет трудно сериализовать полиморфные типы, экзистенциальные типы и функции.

5 голосов
/ 22 апреля 2010

Вы хотели

сделать скучную работу по превращению типа данных в haskell в объект строки JSON / XML / DB и обратно в объект данных.

Существует множество способов сериализации и десериализации типов данных в Haskell. Вы можете использовать, например,

, а также другие распространенные форманты ( протокол буфера , thrift , xml)

Каждый пакет часто / обычно поставляется с макросом или механизмом получения, который позволяет вам, например, вывести JSON. Например, для Data.Binary см. Предыдущий ответ: term_to_binary Эрланга в Haskell?

Общий ответ таков: у нас есть много отличных пакетов для сериализации в Haskell, и мы склонны использовать существующую инфраструктуру «производного» класса (для создания производных используются либо универсальные шаблоны, либо макросы шаблона Haskell).

5 голосов
/ 22 апреля 2010

Несмотря на это, я думаю, что решение для препроцессора, найденное в OCaml (примером которого являются, например, sexplib, binprot и json-wheel), довольно хорошо (и я думаю, что люди делают очень похожие вещи с Template Haskell). Это гораздо более эффективно, чем отражение, и также может быть настроено на отдельные типы естественным образом. Если вам не нравится автоматически сгенерированный сериализатор для данного типа foo, вы всегда можете просто написать свой собственный, и он прекрасно вписывается в автоматически сгенерированные сериализаторы для типов, которые включают foo в качестве компонента.

Единственным недостатком является то, что вам нужно изучить camlp4, чтобы написать один из них для себя. Но использовать их довольно просто, когда вы настроите свою систему сборки на использование препроцессора. Это так же просто, как добавление with sexp в конец определения типа:

type t = { foo: int; bar: float }
with sexp

и теперь у вас есть сериализатор.

4 голосов
/ 22 апреля 2010

Насколько я понимаю, самый простой способ сериализации и десериализации в Haskell - это получить из Read и Show. Это просто и не полностью соответствует вашим требованиям.

Однако есть HXT и Text.JSON , которые, кажется, обеспечивают то, что вам нужно.

3 голосов
/ 22 апреля 2010

Обычный подход заключается в использовании Data.Binary . Это обеспечивает базовую возможность сериализации. Двоичные экземпляры для типов данных легко записываются и могут быть легко созданы из более мелких блоков.

Если вы хотите автоматически генерировать экземпляры, вы можете использовать Template Haskell. Я не знаю ни одного пакета для этого, но я не удивлюсь, если он уже существует.

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