如何对数据对象进行自动数据序列化?

Ada*_*ent 15 serialization ocaml haskell

具有某种反射/内省规范的语言的巨大好处之一是可以从各种来源自动构建对象.

例如,在Java中,我可以使用相同的对象来持久化到db(使用Hibernate),序列化为XML(使用JAXB),以及序列化为JSON(json-lib).您可以在Ruby和Python中执行相同的操作,通常也遵循一些简单的Java属性或注释规则.

因此,我不需要很多"域转移对象".我可以专注于我正在工作的领域.

它似乎在像Haskell和Ocaml这样非常严格的FP中,这是不可能的.特别是Haskell.我唯一看到的是进行某种预处理或元编程(ocaml).只是接受你必须从底部向上进行所有转换吗?

换句话说,您必须做很多无聊的工作才能将haskell中的数据类型转换为JSON/XML/DB Row对象,然后再转换回数据对象.

C. *_*ann 28

我不能和OCaml说话,但我要说Haskell的主要困难是反序列化需要提前知道类型 -没有通用的方法从格式中进行机械反序列化,弄清楚结果值是什么,以及从那里开始,尽可能使用不健全或动态类型系统的语言.

抛开类型问题,有各种方法在Haskell中序列化数据:

  • 内置类型Read/ Show(de)将代数数据类型和大多数内置类型序列化为字符串.表现良好的实例通常应该read . show等同于id,并且结果show可以解析为构造序列化值的Haskell源代码.

  • 可以在Hackage上找到各种序列化包; 通常这些要求要序列化的类型是某个类型类的实例,该包提供大多数内置类型的实例.有时它们只需要一个自动派生的类型实现,反射元编程Data类的实例(它的迷人完全限定名称Data.Data.Data),或者提供模板Haskell代码来自动生成实例.

  • 对于真正不寻常的序列化格式 - 或者像前面提到的那样创建自己的软件包 - 人们可以获得最大的锤子,可以选择"大哥" ReadShow解析和漂亮打印.两者都有许多软件包,虽然起初可能听起来令人生畏,但在Haskell中,解析和漂亮打印实际上是非常轻松的.

浏览Hackage表明已经存在各种格式的序列化包,包括二进制数据,JSON,YAML和XML,虽然我没有使用它们,所以我无法亲自证明它们的工作情况.这是一个非详尽的列表,可以帮助您入门:

  • 二进制:面向性能的序列化到懒惰ByteString
  • 谷物:类似于二进制,但接口略有不同,并使用严格的ByteStrings
  • genericserialize:通过内置元编程进行序列化,输出格式是可扩展的,包括R5RS sexp输出.
  • json:JSON数据的轻量级序列化
  • RJson:通过内置元编程将序列化为 JSON
  • hexpat-pickle:使用"hexpat"包序列化为XML的组合器
  • regular-xmlpickler:使用"常规"包将递归数据结构序列化为 XML

唯一的另一个问题是,不可避免地,并非所有类型都可以序列化 - 如果没有别的,我怀疑你将很难序列化多态类型,存在类型和函数.

  • @Adam Gent:嗯,据我所知,使用内置通用元编程的软件包几乎是自动的,只需要`Data`和/或`Typeable`的实例,这两个实例都可以由GHC自动派生.所有需要的是一个`derived(Data,Typeable)`子句添加到任何`data` /`newtype`定义,就像经常使用`Show`,`Eq`等自动派生实例一样. (6认同)
  • 我想补充说有一个更新的库[aeson](http://hackage.haskell.org/package/aeson)(支持使用`Data`派生实例的自动实例以及使用` DeriveGeneric`).它可能意味着_json_的继承者. (2认同)

zrr*_*zrr 5

对于它的价值,我认为在OCaml中找到的预处理器解决方案(例如sexplib,binprot和json-wheel等)非常棒(我认为人们使用Template Haskell做非常相似的事情).它比反射效率高得多,也可以自然地调整到各种类型.如果您不喜欢给定类型foo的自动生成的序列化程序,您可以随时编写自己的序列化程序,并且它非常适合包含foo作为组件的类型的自动生成的序列化程序.

唯一的缺点是你需要学习camlp4为自己编写其中一个.但是,一旦将构建系统设置为使用预处理器,使用它们就非常容易.它就像添加with sexp到类型定义的末尾一样简单:

type t = { foo: int; bar: float }
with sexp
Run Code Online (Sandbox Code Playgroud)

现在你有了你的序列化器.


Don*_*art 5

你自找的

做很多无聊的工作,将haskell中的数据类型转换为JSON/XML/DB Row对象,然后再转换回数据对象.

在Haskell中有许多方法可以序列化和反序列化数据类型.你可以用,例如,

以及其他常见共振峰(协议缓冲区,thrift,xml)

每个包经常/通常带有宏或派生机制,以允许您例如派生JSON.例如,对于Data.Binary,请参阅前面的答案:Erask在Haskell中的term_to_binary?

一般的答案是:我们在Haskell中有很多很好的序列化包,我们倾向于使用现有的类'derived''基础结构(使用泛型或模板Haskell宏来进行实际派生).