一种“覆盖”/“强制”某种隐式解决方案的安全方法

时间:2016-02-24 13:00:51

标签: scala playframework

我有MyFormat的自定义格式化程序(例如org.joda.DateTime),它提供Format[org.joda.DateTime]

Play为play.api.libs.json包中的同一个类提供默认格式化程序。

我想在我的应用程序中使用MyFormat,而不是Play提供的那个。我已经通过显式导入/ mixins完成了这个工作,但是在更改或遗漏时,当这些被删除时,序列化默认为Play格式化程序,我最终会遇到运行时错误。这似乎非常容易出错。

最终,如果需要一个MyFormat范围内的org.joda.DateTime,我希望我的代码不要编译。

有没有一种安全可靠的方法呢?

1 个答案:

答案 0 :(得分:0)

你有两个选择,但它们都不是你想要的。问题的关键在于Scala将在相关的伴随对象中寻找隐含。例如,如果需要查找隐式Format[DateTime],它将在Format的伴随对象和DateTime的伴随对象中查找。在这种情况下,Format内的隐式def会产生所需的(或者在你的情况下,不需要的)Format[DateTime]并且没有什么可以摆脱它,除了分叉和黑客播放。

解决方法1 :使用自定义格式化程序创建对象,并将其全局导入:

package my.project

object Formats {
    implicit val dateTimeFormat: Format[DateTime] = ???
}

(在其他文件中)

import my.project.Formats._

导入到本地范围的Format[DateTime]将取代从Format对象解析的DateTime。但是,如果没有它,您就无法阻止代码编译(除非您有某种scalastyle规则或需要导入的东西)。

解决方法2 :使用Format创建DateTime的包装器,并将其隐式转换为case class MyDateTime(dt: DateTime) { implicit def toDateTime: DateTime = dt } object MyDateTime { implicit val fmt: Format[MyDateTime] = ??? implicit def fromDateTime(dt: DateTime): MyDateTime = MyDateTime(dt) }

DateTime

这不是一个完整的例子,而是关于如何实现它的想法。 MyDateTime可以与大多数地方MyDateTime进行交换,但可能需要围绕ToStatement[MyDateTime]进行其他隐含。例如,当我尝试将它与Anorm一起使用时,我需要一个隐式的Format[DateTime],可能还需要一些其他的 - 所以这是明显的缺点。但是,这将明确避​​免使用默认的itemizedlist