我想构建一个 Scala DSL 以将现有的 Java POJO 结构转换为等效于 Map 的结构。
然而,传入的对象结构很可能包含大量空引用,这将导致输出映射中没有值。
在这种情况下,性能非常重要,因此我需要避免反射和抛出/捕获 NPE。
我已经考虑过这个不符合我要求的主题。
我认为答案可能在于使用宏来生成一些特殊类型,但我没有使用 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 中正确完成了类型检查)。