2017-04-05 64 views
0

问题的简短故事在标题中。有一些Java类,例如org.joda.time.Interval,我想(不重写它)使其成为案例类,即具有applyunapply方法。是否有可能为现有的Java bean类获取Scala案例类?

长的故事:我有一个Scala的播放应用程序,有我定义的形式,需要两个区间,即

import org.joda.time.Interval 

case class MyParams(param1: String, interval1: Interval, interval2: Interval) 

,然后我试图定义嵌套映射,但Interval是一个Java类,并没有按”没有apply/unapply,我宁愿不创建我自己的副本。

val myForm = Form { 
     mapping(
     "param1" -> nonEmptyText, 
     "interval1" -> mapping(
      "start" -> jodaDate, 
      "end" -> jodaDate, 
     )(Interval.apply)(Interval.unapply), // <<<<<<<<<< Cannot resolve symbol ... 
     "interval2" -> mapping(
      "start" -> jodaDate, 
      "end" -> jodaDate, 
     )(Interval.apply)(Interval.unapply) // <<<<<<<<<< Cannot resolve symbol ... 
    )(MyParams.apply)(MyParams.unapply) 
} 

当然,我可以扁平化结构,但这样做不会很好地扩展设计方面再加上有,将需要组成现有JSON复合材料结构,我想重用绑定到窗体这两个JSON请求和表单提交。作为补充

object IntervalUtils { 
    implicit object Interval { 
    def apply(start: DateTime, end: DateTime) = new org.joda.time.Interval(start, end) 
    def unapply(interval: org.joda.time.Interval) = Some((interval.getStart, interval.getEnd)) 
    } 
} 

所以OP的代码编译为只缺少import IntervalUtils._然后:

UPDATE建设上公认的答案的顶部,并采取语法糖顾及我在最后做奖金也可以这样做:

implicit val jodaIntervalWrites = new Writes[org.joda.time.Interval] { 
    def writes(interval: org.joda.time.Interval) = Json.obj(
    "start" -> interval.getStart, 
    "end" -> interval.getEnd 
) 
} 

implicit val jodaIntervalReads: Reads[org.joda.time.Interval] = (
    (JsPath \ "start").read[DateTime] and 
    (JsPath \ "end").read[DateTime] 
)(Interval.apply _) // <<<<<<<<<<<<<<<<<< reused here 

回答

2

要做到这一点,你并不需要的情况下类,你只需要两个方法用合适的签名,您可以轻松地将它们定义:

object JodaTime { 
    def mkInterval(start: ReadableInstant, end: ReadableInstant) = new Interval(start, end) 
    def unmkInterval(interval: Interval) = Some((interval.getStart, interval.getEnd)) 
} 

// elsewhere 
mapping(
    "start" -> jodaDate, 
    "end" -> jodaDate, 
)(JodaTime.mkInterval)(JodaTime.unmkInterval) 

事实上,你甚至不需要mkInterval,你可以只写new Interval(_, _)(不知道是否超载可能会导致这个特定用例的一个问题,但如果是这样只需指定占位符类型)。