конвертировать объекты Java в типы Clojure

Привет. В настоящее время я использую java.data (https://github.com/clojure/java.data) для преобразования java pojos в типы, совместимые с clojure. Это не работает для вложенных объектов.

Например:

class Abc {
   Map<String, Def> someMap;
}

Class Def {
   String b;
}

Если я передам пример экземпляра Abc в java.data, я получу вывод как:

   {
      :someMap { 
         "keyString" #object[com.sample.Def 0xb33584d "com.sample.Def@b33584d"]
      }
   }

Но я хочу, чтобы результат был таким:

   {
       :someMap { 
            "keyString" {
                 "b" "value" 
            } 
       }
   }

Как я могу это исправить?

Я попробовал бин clojure.core (https://clojuredocs.org/clojure.core/bean ) и это, похоже, тоже не работает.

Заранее спасибо.


person ppp456878    schedule 26.09.2020    source источник


Ответы (2)


Чтобы это работало, ваши объекты Java должны соответствовать спецификации JavaBean. . Это означает, что им нужны методы .getXXX() для чтения свойств объекта (как минимум), а также .setXXX() для построения новый объект. Пример:

Класс Inner:

package demo;
public class Inner {
    public String secret;
    public String getSecret() {
        return secret;
    }    
    public Inner(String arg) {
        this.secret = arg;
    }
}

Класс Outer:

package demo;
import java.util.HashMap;
import demo.Inner;

public class Outer {
  public HashMap<String, Inner> someMap;

  public Outer() {
    HashMap<String,Inner> hm = new HashMap<String, Inner>();
    hm.put("stuff", new Inner( "happens"));
    hm.put("another", new Inner( "thing"));
    this.someMap = hm;
  }

  public HashMap getSomeMap() { return someMap; }
}

и код Clojure для декодирования вложенных объектов JavaBean:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [clojure.java.data :as jd])
  (:import [demo Calc]))

(dotest
  (let [java-obj    (Outer.)
        obj-shallow (jd/from-java java-obj)
        obj-deep    (jd/from-java-deep java-obj {})]
    (spyx         java-obj)
    (spyx         obj-shallow)
    (spyx-pretty  obj-deep)
    ))

Результаты показывают, что происходит:

--------------------------------------
   Clojure 1.10.2-alpha1    Java 14
--------------------------------------

lein test tst.demo.core
java-obj     => #object[demo.Outer 0x138d8219 "demo.Outer@138d8219"]
obj-shallow  => {:someMap {"another" #object[demo.Inner 0x8d86c4d "demo.Inner@8d86c4d"], "stuff" #object[demo.Inner 0x28c92c51 "demo.Inner@28c92c51"]}}
obj-deep     => {:someMap {"another" {:secret "thing"}, 
                           "stuff"   {:secret "happens"}}}

Необработанный java-obj непрозрачен для Clojure. Использование jd/from-java распаковывает только внешний слой с помощью геттеров JavaBean. Использование jd/from-java-deep (обратите внимание на карту обязательных опций, оставленную здесь пустой) будет рекурсивно распаковывать JavaBean, используя соответствующие геттеры для каждого объекта на основе его класса java.

Весь приведенный выше код основан на этом проекте шаблона. Наслаждаться!

person Alan Thompson    schedule 26.09.2020

Встроенная в Clojure функция bean выполняет только поверхностное преобразование — она не рекурсивно преобразует какую-либо вложенную информацию. Посетите https://github.com/clojure/java.data для рекурсивного преобразования из Объекты Java в структуры данных Clojure (и обратно).

java.data также поддерживает Java API в стиле компоновщика, что упрощает создание объектов Java из Clojure.

person Sean Corfield    schedule 26.09.2020