从 clojure 映射创建 java bean

Creating a java bean from a clojure map

clojure.core 提供从 java 对象创建 clojure 映射的 bean 但是是否有一个从映射创建 bean(java 对象)的反函数?

具体取决于您的需要。

Bean 类型存在于 Java

换句话说,您的 java 项目中有(比方说)一个 Customer.class,您希望根据地图中的数据通过 Clojure 对其进行实例化和填充.这可以通过 java interop.

简单地完成

Clojure 中创建的 Bean 类型

您可以手动使用 AOT compilation to create a Javabean type, which will result in a .class file on the disk and can be used in a Java project (in the same way as any Java class, that does not have a corresponding Java source). You can use the clj-bean library to avoid using gen-class

在 Clojure 中创建的 Bean 类型 - 动态地,没有 .class 文件

在这种情况下,您可以使用 deftype 通过动态字节码创建来创建 bean(只需为 getter 和 setter 创建方法并将数据从地图移动到地图)。

以上所有方式你都可以找到例子in this project

有各种库可以执行 Clojure map <-> Java Bean 翻译,包括我编写的一个名为 bean-dip. Here's the breakdown in the README on the other options considered and what distinguishes bean-dip:

...

Existing translation solutions had feature gaps that lead us to create bean-dip: The clojure.core/bean built-in is one-way, uses uncached reflection and can't be configured. Cached reflection is available via gavagai, but it's only one-way. There's java.data, which is bidirectional, recursive and reflection-free, but it's not declarative making large translation layers hard to maintain.

Bean-dip is:

  • Bidirectional: Translate from beans to maps and back again
  • Declarative: Just specify the bean class and a set of keys for corresponding maps
  • Recursive: Translation descends into nested beans when they also have translations defined
  • Reflection-free: Macro generates type hinted code that can be name checked at compile time via *warn-on-reflection*
  • Extensible: Translate values by key via implementations of multimethods

Namespaced keys are supported making it easy to enforce contracts with Java APIs using specs...