使用Java对象作为Clojure映射

Mat*_*ick 16 java clojure clojure-java-interop

我有一个我想在Clojure中使用的Java类.但是,我想将它用作Clojure地图.这样做的步骤是什么?

我查看了代码IPersistentMap- 如果Java类实现了吗?或者是否应该有一些实现协议的Clojure代码?

我知道我可以编写一些映射代码,将代码从Java对象显式转换为映射,但该解决方案具有很高的努力/回报率.此外,我可能会多次遇到同样的情况.


具体示例:我有一个用Java编写的解析器.我想使用它来解析一些文本,然后访问解析数据结构的内容,就像它在Clojure映射中一样:

(def parser (new MyParser))

(let [parse-tree (parser ... parse some text ...)]
  ((parse-tree :items) "itemid"))
Run Code Online (Sandbox Code Playgroud)

unp*_*680 23

这个功能bean浮现在脑海中:

获取Java对象并基于其JavaBean属性返回映射抽象的只读实现.

从网站上取的示例:

user=> (import java.util.Date)
java.util.Date

user=> (def *now* (Date.))
#'user/*now*

user=> (bean *now*)
{:seconds 57, :date 13, :class java.util.Date,
 :minutes 55, :hours 17, :year 110, :timezoneOffset -330,
 :month 6, :day 2, :time 1279023957492}
Run Code Online (Sandbox Code Playgroud)

  • 看看clojure.java.data.有一个函数(from-java)递归使用java.beans.Introspector.此外,您可以通过将... BeanInfo类添加到java库来控制哪些get ...方法被识别,以及重命名clojure映射中使用的关键字,来优化from-java的输出. (7认同)

小智 5

当然(bean javaObject)(参见bean ClojureDoc)运行良好,但它不会让你选择你想要的属性和你没有的属性.将结果映射输入json-str函数时会产生影响,在这种情况下,您可能会收到错误消息:"不知道如何编写JSON ..."

而且我发现恼人的,当我处理基本上接受JSON(像底层的NoSQL数据库(MongoDB中,Neo4j的)新保守主义者).

那么我的解决方案是什么?

(defmacro get-map-from-object-props [object & props]
  ;->> will eval and reorder the next list starting from the end
  (->> (identity props) ;identity is here to return the 'props' seq
       ;map each property with their name as key and the java object invocation as the value
       ;the ~@ is here to unsplice the few properties
       (map (fn [prop] [(keyword (str prop)) `(.. ~object ~@(prop-symbol prop) )]))
       (into {})))

;getter is a simple function that transform a property name to its getter "name" -> "getName"
(defn prop-symbol [prop]
  (map symbol (map getter (clojure.string/split (str prop) #"\\."))))
Run Code Online (Sandbox Code Playgroud)

并且你可以像这样使用它(是的,如果有的话,函数会处理一系列属性)

(get-map-from-object-props javaObject property1 property2 property3.property1)
Run Code Online (Sandbox Code Playgroud)

希望能帮助别人......