我想構建一個Scala DSL以將Java POJO的現有結構轉換爲等效於Map的結構。用於Scala中安全導航運算符的DSL
但是,傳入對象結構很可能包含大量空引用,這將導致輸出映射中沒有值。
在這方面的表現非常重要,所以我需要避免反射和拋/ NPE。
我已經認爲已經不符合我的要求this topic。
我認爲答案可能在於使用宏來生成一些特殊的類型,但我沒有使用scala宏的經驗。
更正式地說:由項目提供
POJO類:(會有像50 POJO,嵌套的,所以我想這並不需要手工編寫和維護他們每一類或性狀的解決方案)
case class Level1(
@BeanProperty var a: String,
@BeanProperty var b: Int)
case class Level2(
@BeanProperty var p: Level1,
@BeanProperty var b: Int)
預期的行爲:
println(convert(null)) // == Map()
println(convert(Level2(null, 3))) // == Map("l2.b" -> 3)
println(convert(Level2(Level1("a", 2), 3))) // == Map(l2.p.a -> a, l2.p.b -> 2, l2.b -> 3)
正確執行,但我想一個更簡單的DSL寫的映射
implicit def toOptionBuilder[T](f: => T) = new {
def ? : Option[T] = Option(f)
}
def convert(l2: Level2): Map[String, _] = l2? match {
case None => Map()
case Some(o2) => convert(o2.p, "l2.p.") + ("l2.b" -> o2.b)
}
def convert(l1: Level1, prefix: String = ""): Map[String, _] = l1? match {
case None => Map()
case Some(o1) => Map(
prefix + "a" -> o1.a,
prefix + "b" -> o1.b)
}
這裏是我想用一個DSL寫:「?」
def convertDsl(l2:Level2)={
Map(
"l2.b" -> l2?.b,
"l2.p.a" -> l2?.l1?.a,
"l2.p.b" -> l2?.l1?.b
)
}
請注意,這是完全正常,我指定的屬性是可選的。 我想要的是使用宏來靜態生成一個方法l2.?l1或l2?.l1,它返回Option [Level1](因此類型檢查在我的DSL中正確完成)。
我被暗示在郵件列表中使用宏quasiquotes,但目前在scala 2.10中實現似乎有點棘手。 http://docs.scala-lang.org/overviews/macros/quasiquotes.html; https://gist.github.com/anonymous/7ab617d054f28d68901b; http://docs.scala-lang.org/overviews/macros/paradise。html#macro_paradise_for_210x –