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

发布于 2024-08-29 11:23:20 字数 412 浏览 3 评论 0 原文

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

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

因此我不需要很多“域传输对象”。我可以专注于我正在工作的领域。

在像 Haskell 和 Ocaml 这样非常严格的 FP 中,这似乎是不可能的。 特别是哈斯克尔。我所看到的唯一的事情就是进行某种预处理或元编程(ocaml)。难道所有的转变都必须从下往上进行吗?

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

One of the huge benefits in languages that have some sort of reflection/introspecition is that objects can be automatically constructed from a variety of sources.

For example, in Java I can use the same objects for persisting to a db (with Hibernate), serializing to XML (with JAXB), and serializing to JSON (json-lib). You can do the same in Ruby and Python also usually following some simple rules for properties or annotations for Java.

Thus I don't need lots "Domain Transfer Objects". I can concentrate on the domain I am working in.

It seems in very strict FP like Haskell and Ocaml this is not possible.
Particularly Haskell. The only thing I have seen is doing some sort of preprocessing or meta-programming (ocaml). Is it just accepted that you have to do all the transformations from the bottom upwards?

In other words you have to do lots of boring work to turn a data type in haskell into a JSON/XML/DB Row object and back again into a data object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

留蓝 2024-09-05 11:23:20

我无法与 OCaml 交谈,但我想说 Haskell 的主要困难是反序列化需要提前知道类型——没有通用的方法可以从格式中机械地反序列化,弄清楚结果值是什么,并从那里开始,这在具有不健全或动态类型系统的语言中是可能的。

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

  • 内置类型类 Read/Show (反)序列化代数数据类型和大多数内置类型都是字符串。行为良好的实例通常应该是 read 。 show 相当于 id,并且 show 的结果可以解析为构造序列化值的 Haskell 源代码。

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

  • 对于真正不寻常的序列化格式 - 或者创建您自己的包,如前面提到的那样 - 人们可以使用可用的最大锤子,有点像“老大哥”来阅读和< code>Show:解析和漂亮打印。有许多软件包可用于这两种格式,虽然一开始听起来可能令人生畏,但实际上 Haskell 中的解析和漂亮打印非常轻松。

浏览一下 Hackage 就会发现,已经存在各种格式的序列化包,包括二进制数据、JSON、YAML 和 XML,尽管我没有使用过它们中的任何一个,所以我无法亲自证明它们的工作效果如何。下面是一个帮助您入门的非详尽列表:

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

唯一的其他问题是,不可避免的是,并非所有类型都可序列化——如果不出意外的话,我怀疑您将会有一个很难序列化多态类型、存在类型和函数。

I can't speak to OCaml, but I'd say that the main difficulty in Haskell is that deserialization requires knowing the type in advance--there's no universal way to mechanically deserialize from a format, figure out what the resulting value is, and go from there, as is possible in languages with unsound or dynamic type systems.

Setting aside the type issue, there are various approaches to serializing data in Haskell:

  • The built-in type classes Read/Show (de)serialize algebraic data types and most built-in types as strings. Well-behaved instances should generally be such that read . show is equivalent to id, and that the result of show can be parsed as Haskell source code constructing the serialized value.

  • Various serialization packages can be found on Hackage; typically these require that the type to be serialized be an instance of some type class, with the package providing instances for most built-in types. Sometimes they merely require an automatically derivable instance of the type-reifying, reflective metaprogramming Data class (the charming fully qualified name for which is Data.Data.Data), or provide Template Haskell code to auto-generate instances.

  • For truly unusual serialization formats--or to create your own package like the previously mentioned ones--one can reach for the biggest hammer available, sort of a "big brother" to Read and Show: parsing and pretty-printing. Numerous packages are available for both, and while it may sound intimidating at first, parsing and pretty-printing are in fact amazingly painless in Haskell.

A glance at Hackage indicates that serialization packages already exist for various formats, including binary data, JSON, YAML, and XML, though I've not used any of them so I can't personally attest to how well they work. Here's a non-exhaustive list to get you started:

  • binary: Performance-oriented serialization to lazy ByteStrings
  • cereal: Similar to binary, but a slightly different interface and uses strict ByteStrings
  • genericserialize: Serialization via built-in metaprogramming, output format is extensible, includes R5RS sexp output.
  • json: Lightweight serialization of JSON data
  • RJson: Serialization to JSON via built-in metaprogramming
  • hexpat-pickle: Combinators for serialization to XML, using the "hexpat" package
  • regular-xmlpickler: Serialization to XML of recursive data structures using the "regular" package

The only other problem is that, inevitably, not all types will be serializable--if nothing else, I suspect you're going to have a hard time serializing polymorphic types, existential types, and functions.

╭⌒浅淡时光〆 2024-09-05 11:23:20

就其价值而言,我认为 OCaml 中的预处理器解决方案(例如 sexplib、binprot 和 json-wheel 等)非常好(而且我认为人们使用 Template Haskell 做非常类似的事情)。它比反射更有效,并且还可以以自然的方式调整为个别类型。如果您不喜欢给定类型 foo 的自动生成的序列化器,您始终可以编写自己的序列化器,并且它非常适合包含 foo 作为组件的类型的自动生成的序列化器。

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

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

现在您就拥有了序列化器。

For what it's worth, I think the pre-processor solution found in OCaml (as exemplified by sexplib, binprot and json-wheel among others) is pretty great (and I think people do very similar things with Template Haskell). It's far more efficient than reflection, and can also be tuned to individual types in a natural way. If you don't like the auto-generated serializer for a given type foo, you can always just write your own, and it fits beautifully into the auto-generated serializers for types that include foo as a component.

The only downside is that you need to learn camlp4 to write one of these for yourself. But using them is quite easy, once you get your build-system set up to use the preprocessor. It's as simple as adding with sexp to the end of a type definition:

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

and now you have your serializer.

晚雾 2024-09-05 11:23:20

你想要

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

Haskell 中有多种方法可以序列化和反序列化数据类型。例如,您可以使用

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

每个包通常/通常带有宏或派生机制,以允许您派生 JSON。例如,对于 Data.Binary,请参阅之前的答案:Erlang's term_to_binary in Haskell?

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

You wanted

to do lot of boring work to turn a data type in haskell into JSON/XML/DB Row object and back again into a data object.

There are many ways to serialize and unserialize data types in Haskell. You can use for example,

as well as other common formants (protocol buffers, thrift, xml)

Each package often/usually comes with a macro or deriving mechanism to allow you to e.g. derive JSON. For Data.Binary for example, see this previous answer: Erlang's term_to_binary in Haskell?

The general answer is: we have many great packages for serialization in Haskell, and we tend to use the existing class 'deriving' infrastructure (with either generics or template Haskell macros to do the actual deriving).

-黛色若梦 2024-09-05 11:23:20

我的理解是,在 Haskell 中序列化和反序列化的最简单方法是从 ReadShow 派生。这很简单,并不能满足您的要求。

但是,还有 HXTText.JSON 这似乎提供了您所需要的。

My understanding is that the simplest way to serialize and deserialize in Haskell is to derive from Read and Show. This is simple and isn't fullfilling your requirements.

However there are HXT and Text.JSON which seem to provide what you need.

壹場煙雨 2024-09-05 11:23:20

通常的方法是使用 Data.Binary。这提供了基本的序列化功能。数据类型的二进制实例易于编写,并且可以轻松地由较小的单元构建。

如果你想自动生成实例,那么你可以使用 Template Haskell。我不知道有任何软件包可以做到这一点,但如果已经存在,我不会感到惊讶。

The usual approach is to employ Data.Binary. This provides the basic serialisation capability. Binary instances for data types are easy to write and can easily be built out of smaller units.

If you want to generate the instances automatically then you can use Template Haskell. I don't know of any package to do this, but I wouldn't be surprised if one already exists.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文